This question already has answers here:
JSON Parse error: Unrecognized token'<' - react-native
(16 answers)
Closed 2 years ago.
I'm learning react native. here I am making a login logout API to use clien.
when i try in postman, the result is right and right but when I use the API,
I get a problem which is:
JSON Parse error: Unrecognized token '<'
this my code
class AuthScene extends Component {
constructor(props) {
super(props);
this.state = {
username : '',
password : ''
}
}
login= ()=>{
const {username,password} = this.state;
// alert(username);
fetch('https://example.com/auth', {
method: 'POST',
headers: {
'Accept' : 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
password: password
})
})
.then((response) => response.json()).then((responseJson) => {
alert(JSON.stringify(responseJson));
console.log(JSON.stringify(responseJson, null, 4))
}).catch((error) => {
alert(JSON.stringify(error));
console.log(error);
// done();
});
}
and
render() {
return (
<Form style={styles.mainForm}>
<Item style={styles.formItems}>
<Input placeholder="Username" style={styles.Input} onChangeText={username => this.setState({username})}/>
</Item>
<Item style={styles.formItems}>
<Input style={styles.Input} secureTextEntry={true} onChangeText={(password) => this.setState({password})}/>
</Item>
<View style={styles.Button}>
<Button block info style={styles.mainBtn} onPress={this.login}>
<Text style={styles.btnText}>Submit</Text>
</Button>
</View>
</Form>
);
}
how to deal with those things?
Is there a problem with my json or my code isn't correct?
Please check your headers in code is matching with the postman or not..
Related
I am creating an app using expo. You can check the snack here
I am also giving the code here:
import React, {Component} from 'react';
import { ActivityIndicator, Text, View, StyleSheet, FlatList, Alert, TouchableOpacity } from 'react-native';
import {Avatar, Card, Button, Divider, ListItem, Image} from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import Constants from 'expo-constants';
import HTML from 'react-native-render-html';
import UserAvatar from 'react-native-user-avatar';
import { StackNavigator } from 'react-navigation';
import { createAppContainer} from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
class HomeScreen extends React.Component{
static navigationOptions =
{
title: '',
};
constructor(props){
super(props);
this.state = {
Loading : true,
data : []
}
}
fetchLeash(){
fetch('https://lishup.com/app/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({ data: responseJson, Loading:false });
}).catch((error) => {
Alert.alert('error!');
});
}
fetchImage(getimg){
fetch('https://lishup.com/app/fetch-image.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
image: getimg
})
}).then((response) => response.json())
.then((responseJson) => {
return (<Text>responseJson.url</Text>);
}).catch((error) => {
Alert.alert('error');
});
}
componentDidMount(){
this.fetchLeash();
}
renderLeash = ({ item }) => (
<View>
<Card style={{ height:100, justifyContent: 'center', alignItems: 'center' }}>
<ListItem
leftAvatar={{
title: item.user,
source: { uri: item.userpic },
}}
title={item.user}
subtitle={item.time}
chevron
/>
<Divider style={{margin:5, backgroundColor:'white'}} />
<HTML html={item.text} />
{this.fetchImage(item.images)}
</Card>
</View>
)
render(){
if(this.state.Loading == true){
return(
<ActivityIndicator size="large" style={{marginTop:100}} color="#0000ff" />
);
}else{
return(
<View>
<FlatList style={{width:400}}
data={this.state.data}
renderItem={this.renderLeash} />
</View>
);
}
}
}
const styles = StyleSheet.create({
});
const RootStack = createStackNavigator(
{
Home: { screen: HomeScreen },
},
{
initialRouteName: 'Home',
}
);
export default createAppContainer(RootStack);
If you run the snack in your device, you will see that the posts(fetchLeash() function) is working fine. But the fetchImage() is returning nothing.
My fetch-image.php file is here:
<?php
// Importing DBConfig.php file.
include 'DB.php';
header('Content-Type: application/json');
// Creating connection.
$con = mysqli_connect($HostName,$HostUser,$HostPass,$DatabaseName);
// Getting the received JSON into $json variable.
$json = file_get_contents('php://input');
// decoding the received JSON and store into $obj variable.
$obj = json_decode($json,true);
// Populate User email from JSON $obj array and store into $email.
$image = $obj['image'];
if($image == "") {
$blank[] = array("url"=>"");
echo json_encode($blank);
}else{
//query to get image url with the code received
$Sql_Query = "SELECT * FROM `leash_img` WHERE `pid`= '".$image."' ";
// Executing SQL Query.
$check = mysqli_query($con,$Sql_Query);
if($check){
while($row=mysqli_fetch_assoc($check)){
$SuccessLoginMsg[] = array("url"=> $row['image']);
}
// Converting the message into JSON format.
$SuccessLoginJson = json_encode($SuccessLoginMsg);
echo $SuccessLoginJson;
}
}
?>
This returns like the following:
[{"url":"link here"}]
The PHP file is working fine. But the react native fetchImage() is not working.
I am totally new to react native. So forgive my problems. I am just out of my ideas. Please help me.
You can't asynchronously render UI from the render function, you need to fetch the data outside it in one of the lifecycle functions and conditionally render UI while it is being fetched.
Once the data has been fetched you should go ahead and fetch the image urls. Use Promise.all and map each response item to a fetch request. This will allow all image url fetches to resolve asynchronously and maintain index order.
fetchLeash() {
fetch('https://lishup.com/app/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({ data: responseJson });
Promise.all(responseJson.map(({ images }) => this.fetchImage(images)))
.then((images) => {
this.setState({ imageUrls: images.map(url => ({ uri: url })) })
});
})
.catch((error) => {
Alert.alert('error!');
})
.finally(() => {
this.setState({ Loading: false });
});
}
The other important change is that the image response is an array of length 1, so need to access correctly.
fetchImage(image) {
return fetch('https://lishup.com/app/fetch-image.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ image }),
})
.then((response) => response.json())
.then((responseJson) => responseJson[0].url);
}
Now you can conditionally render an Image if the url at that index exists.
renderLeash = ({ item, index }) => (
<View>
<Card
style={{ height: 100, justifyContent: 'center', alignItems: 'center' }}>
<ListItem
leftAvatar={{
title: item.user,
source: { uri: item.userpic },
}}
title={item.user}
subtitle={item.time}
chevron
/>
<Divider style={{ margin: 5, backgroundColor: 'white' }} />
<HTML html={item.text} />
<Text>
{this.state.imageUrls[index] && this.state.imageUrls[index].uri}
</Text>
{this.state.imageUrls[index] && (
<Image
source={this.state.imageUrls[index]}
style={{ width: 100, height: 100 }}
PlaceholderContent={<ActivityIndicator />}
/>
)}
</Card>
</View>
);
Expo Snack
EDIT Allow display of all fetched image URLs. Instead of grabbing and returning just the first URL, return an array of URLs. Below I mapped the URLs to a new array before returning them, and these can be set directly in state now. Update the render function to use an additional guard (array length check) and render null if array doesn't exist. (Could also use another FlatList here if you wanted to)
fetchLeash() {
return fetch('https://lishup.com/app/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({ data: responseJson });
Promise.all(
responseJson.map(({ images }) => this.fetchImage(images))
).then((imageUrls) => this.setState({ imageUrls }));
})
.catch((error) => {
Alert.alert('error!');
})
.finally(() => {
this.setState({ Loading: false });
});
}
fetchImage(image) {
return fetch('https://lishup.com/app/fetch-image.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ image }),
})
.then((response) => response.json())
.then((responseJson) =>
// Filter elements with empty string URLs, then app just the URL
responseJson.filter(({ url }) => url).map(({ url }) => url)
);
}
...
{this.state.imageUrls[index] && this.state.imageUrls[index].length
? this.state.imageUrls[index].map((uri) => (
<Image
source={{ uri }}
style={{ width: 100, height: 100 }}
PlaceholderContent={<ActivityIndicator />}
/>
))
: null}
I am trying to put three params in my post request to particular api but i didn't get the response as i expected. API works fine in my Postman but i am not sure about my fetching method in my react native app i am new to this so i don't know how to put headers in my api request i followed some docs but didn't get much please have a look and answer my question.
constructor (props) {
super (props)
this.state = {
detail: ''
}
}
ComponentDidMount(){
var data = new FormData();
data.append('mobile_number','8615351655')
data.append('mobile_country_code','+21')
data.append('rec_name','Shantanu Talwaar')
}
fetchData = async() => {
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
//this what's exactly look in my postman
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb;
},
body: this.data
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson.detail)
}).catch((error) => {
alert('error')})}
render() {
return (
<View style = {styles.container}>
<Button onPress = {this.fetchData} title = "fetch"/>
<Text style={styles.text}>Fetched data displays below</Text>
<Text style={styles.text}>{this.state.detail}</Text>
</View>
)
}
}
This is the result i am having right now in my alert box: "Authentication credentials were not provided."
There is a ' missing after your token.
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb;
And as it is a JSON Object you should remove the semi-colon
So, the final code will be
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
There is also another problem. The data declaration is not accessible from the fetch function. So you should do something like this.
fetchData = async() => {
var data = new FormData();
data.append('mobile_number','8615351655')
data.append('mobile_country_code','+21')
data.append('rec_name','Shantanu Talwaar')
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
//this what's exactly look in my postman
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
},
body: data
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson.detail)
}).catch((error) => {
alert('error')
})
}
i think you can use "x-access-token" as header name for authentication token and place Content-Type too.
fetchData = () => {
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
'Content-Type': "application/json",
'x-access-token': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
},
body: this.data
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson.detail)
}).catch((error) => {
alert('error')})
}
I'm attempting to build a login form using react create, which consumes the user name and password values from the following json API: https://api.myjson.com/bins/fyufr
The code:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './Login.css';
class Login extends Component {
constructor() {
super();
this.state = {
data: [],
userName: "",
password: "",
token: "",
};
} //end constructor
change = (e) => {
this.setState({
[e.target.name]: e.target.value
});
}; //end change
onSubmit = (e) =>{
e.preventDefault();
console.log(this.state);
this.setState({
userName: "",
password: "",
token: "",
});
var userName = document.getElementById('userName').value
var password = document.getElementById('password').value
for(var i=0; i < this.state.data.length; i++) {
if(userName == this.state.data[i].userName && password == this.state.data[i].password){
console.log(userName + "is logged in")
}
}
console.log("incorrect username or password")
};
componentWillMount() {
fetch('https://api.myjson.com/bins/fyufr', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
},
/*body: JSON.stringify({
username: '{userName}',
password: '{password}'
})*/
}) /*end fetch */
.then(results => results.json())
.then(data => this.setState({ data: data })
)
} //end life cycle
render() {
console.log(this.state.data);
return (
<form>
<input
name="userName"
placeholder="User Name"
value={this.state.userName}
onChange={e => this.change(e) }
/> <br />
<input
name="password"
type="password"
placeholder="Password"
value={this.state.password}
onChange={e => this.change(e) }
/> <br />
<input
name="token"
placeholder="Token"
value={this.state.token}
onChange={e => this.change(e) }
/> <br />
<button onClick={e => this.onSubmit(e)}>Submit</button>
</form>
);
}
}
export default Login;
My code errors out on the following line:
var userName = document.getElementById('userName').value
...the values of this.state.data outputs to the console the values in the json file, but I get the error mentioned above when the submit button is clicked. My goal is to have the login form direct the user to a landing page upon entering a matching username and password, but first, I'm trying to resolve the error am encountering. I'm new to React JS, could I please get some guidance as to what I'm doing wrong?
Simple fix. You are missing id on your form inputs. You are trying to get document.getElementById('userName').value which returns null because it dont exist.
Here's working example of your code: https://stackblitz.com/edit/react-m7iwpt
You haven't set an I'd on your input...
i'm getting the 'unauthorized' error when trying to post a new comment with axios ..... i added (console.log(this.user.api_token);) just before axios.post in postComment() method . the output is : "undefined" !!!!!!!!!!
i'm learning and i don't know much about api's . but i don't think user api_token is to be set up manually .or does it ???
the script :
<script>
const app = new Vue({
el: '#app',
data: {
comments: {},
commentBox: '',
post: {!! $post->toJson() !!},
user: {!! Auth::check() ? Auth::user()->toJson() : 'null' !!}
},
mounted() {
this.getComments();
},
methods: {
getComments() {
axios.get('/api/post/'+this.post.id)
.then((response) => {
this.comments = response.data
})
.catch(function (error) {
console.log(error);
});
},
postComment() {
console.log(this.user.api_token);
axios.post('/api/post/'+this.post.id , {
api_token: this.user.api_token,
body: this.commentBox
})
.then((response) => {
this.comments.unshift(response.data);
this.commentBox = '';
})
.catch((error) => {
console.log(error);
})
}
}
})
api route
Route::get('/post/{post}', 'CommentController#index');
Route::middleware('auth:api')->group(function () {
Route::post('/post/{post}', 'CommentController#store');
});
CommentController
public function index(Post $post){
return response()->json($post->comments()->with('user')->get());
}
public function store(Request $req,Post $post){
$comment=$post->comment()->create([
'user_id'=>auth::id(),
'body'=>$req->body
]);
$comment=Comment::where('id',$comment->id)->with('user')->first();
return $comment->toJson;
}
If you are trying to consume your own api from vuejs there's no need to set the api token manually. Just update the web middleware group in app/Http/Kernel.php to include this line:
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class
This middleware will attach a laravel_token cookie that contains an encrypted JWT that Passport will use to authenticate API requests from your JavaScript application.
Read more here: https://laravel.com/docs/5.6/passport#personal-access-tokens
But, if you are consuming this same api from an external source like a mobile app, an api token will be required by passport to authenticate the request. The token can be created when the user is logged in or registered. Here's how:
//create a token
$token = $user->createToken('Token Name')->accessToken;
Then add an headers object to axios when making a request to the api
axios({
method: 'method',
url: 'url',
headers: {
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$token
}
})
.then()
.catch()
Read more here: https://laravel.com/docs/5.6/passport#managing-personal-access-tokens
When I used SuperAgent I didn't have this problem, but I decided to use Window.fetch polifyl and I met this problem. I see all data was loaded, but it still shows error.
Could your help me identify this error please:
In render() I genereate a list of components based on an obtained list:
render() {
if (this.state.data.list) {
console.log("render: " + this.state.data.list);
var counter = 0;
const list = this.state.data.list.map((item) => {
....
The promise handlers in your screenshot won't work:
.then((json) => console.log('parsed json: ', json))
.then((json) => { this.setState({ data: json }); })
"Take the value from resolving this promise and pass it to console.log. Then, take console.log's return value (which is undefined) and pass it to this.setState."
fetch(url, {
headers: {
'Accept': 'application/json',
},
}).then((response) => response.json()
.catch(err => {
console.err(`'${err}' happened!`);
return {};
}))
.then((json) => {
console.log('parsed json: ', json);
this.setState({ data: json })
})
.catch((err) => { console.log('fetch request failed: ', err) }
)