JSON Parse error: Unrecognized token'<' - in React Native - react-native

I have a problem in React Native. The message is like this JSON Parse error: Unrecognized token '<'. This happens when I do fetch.
import React from 'react';
import { FlatList, ActivityIndicator, Text, View } from 'react-native';
export default class FetchExample extends React.Component {
constructor(props) {
super(props);
this.state ={ isLoading: true}
}
componentDidMount() {
return fetch("http://10.0.3.2:80/api/user", {
headers: {
"Content-Type": "application/json",
"Accept": "application/json, text/plain, */*"
},
method: 'GET'
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.user,
}, function(){
});
})
.catch((error) => {
console.error(error);
});
}
render() {
if(this.state.isLoading) {
return(
<View style={{flex: 1, padding: 20}}>
<ActivityIndicator/>
</View>
)
}
return(
<View style={{flex: 1, paddingTop:20}}>
<FlatList
data={this.state.dataSource}
renderItem={({item}) => <Text>{item.email}</Text>}
keyExtractor={({id}, index) => id}
/>
</View>
);
}
}
This is my JSON. I build in Laravel.
return->response()->json(['user', $user])
["user",[{"id":1,"name":"","email":"danang#gmail.com","email_verified_at":null,"created_at":null,"updated_at":null}]]

I think you json formate is not correct
Please try this json
{
"user":[{
"id":1,
"name":"",
"email":"danang#gmail.com",
"email_verified_at":null,
"created_at":null,
"updated_at":null}]}

Related

How to send bearer token as parameter and retrieve it in another screen in React Native

I want to send bearer token as parameter from one screen and retrieve it another screen and send it too sidebar.
Login.js where i have saved bearer token in const usertoken but can't figure out how to sent it as parameter
import React from 'react';
import {Button,Text,View,Image,TextInput,SafeAreaView,ImageBackground,Alert} from 'react-native';
export default class Login extends React.Component{
constructor(props) {
super(props)
this.state = {
UserName: '',
UserPassword: ''
}
}
UserLoginFunction = () =>{
const { UserName } = this.state ;
const { UserPassword } = this.state ;
fetch('https://api.idepoz.com/ncl/api/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: UserName,
password: UserPassword
})
}).then((response) => response.json())
.then((responseJson) => {
//console.log(responseJson);
if(responseJson)
{
const usertoken = responseJson.token;
this.props.navigation.navigate({routeName:'QrScan'});
}
else{
Alert.alert(responseJson);
}
}).catch((error) => {
console.error(error);
});
}
}
The following is the screen where i want to retrieve the parameter and navigate it to sidebar
import React from 'react';
import { Container, Header, Title, Drawer, Content, Footer, FooterTab, Button, Left, Right, Body, Text } from 'native-base';
import { Alert } from 'react-native';
import { MaterialIcons } from '#expo/vector-icons';
import { Ionicons } from '#expo/vector-icons';
import SideBar from './components/SideBar';
export default class QrScan extends React.Component{
closeDrawer = () => {
this.drawer._root.close();
}
openDrawer = () => {
this.drawer._root.open();
}
render()
{
return(
<Drawer
ref={(ref) => { this.drawer = ref; }}
content={<SideBar navigator={this.navigator} closeDrawer={this.closeDrawer}/>}
onClose={() => this.closeDrawer()} >
<Container>
<Header>
<Left>
<Button transparent onPress={this.openDrawer.bind(this)}>
<MaterialIcons name="list" size={40} color="#FFFFFF" />
</Button>
</Left>
<Body>
<Title></Title>
</Body>
<Right>
<Button transparent>
<Ionicons name="search" size={40} color="#FFFFFF" onPress={() => Alert.alert('Search Button pressed')} />
</Button>
</Right>
</Header>
<Content>
<Text>
</Text>
</Content>
</Container>
</Drawer>
);
}
}
This is the sidebar.js where i want to retrieve the token and use it to logout
import React from 'react';
import { Text, Alert } from 'react-native';
import { Drawer,Container, Content, Header, Right, Button } from 'native-base';
import { FontAwesome } from '#expo/vector-icons';
export default class SideBar extends React.Component {
render() {
return (
<Container>
<Header>
<Right>
<Button transparent>
<FontAwesome name="close" size={24} color="#FFFFFF" onPress={() => this.props.closeDrawer()} />
</Button>
</Right>
</Header>
<Content>
<Button transparent>
<Text style={{fontSize: 24}}>Log Out</Text>
</Button>
</Content>
</Container>
);
}
}
This is a expo project and i am using react navigation 4.4.3.
you can use redux for sharing data from one component to another
https://react-redux.js.org/introduction/basic-tutorial
I found the answer, In Login.js I stored the bearer token inside UserLoginFunction
UserLoginFunction = () =>{
const { UserName } = this.state ;
const { UserPassword } = this.state ;
fetch('https://api.idepoz.com/ncl/api/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: UserName,
password: UserPassword
})
}).then((response) => response.json())
.then((responseJson) => {
if(responseJson)
{
this.props.navigation.navigate('QrScan',{usertoken:responseJson.token});
}
else{
Alert.alert(responseJson);
}
}).catch((error) => {
console.error(error);
});
}
In qrscan.js i retrieved the bearer token like this
constructor(props) {
super(props)
this.state = {
token: ''
}
}
componentDidMount(){
this.setState({
token: this.props.navigation.state.params.usertoken,
})
}
Then i send the token again to sidebar like this inside render
render()
{
// const authtoken= this.props.navigation.getParam('usertoken');
//console.log(this.state.token);
return(
<Drawer
ref={(ref) => { this.drawer = ref; }}
content={<SideBar navigator={this.navigator} closeDrawer={this.closeDrawer} usertoken={this.state.token} />}
onClose={() => this.closeDrawer()} >
<Container>
</Container>
</Drawer>
);
}
I retrieved the bearer token in sidebar like this
render() {
console.log(this.props.usertoken);
return ()
}

React Native filtering API to retrieve specific data

I'm using Zomato API (https://developers.zomato.com/documentation) and am fairly new to getting data from an API, so far I am able to retrieve categories from the API. However what I want to do is pull category data from a specific city. Here is my code:
APIcall.js
import axios from 'axios';
export const apiCall = async(url)=>{
return await axios.request({
baseURL:"https://developers.zomato.com/api/v2.1/categories",
headers: {
'user-key': "a31bd76da32396a27b6906bf0ca707a2",
},
url : url,
method : 'get'
}).then(async(response) => {
return response.data.categories
}).catch(err => console.log(err))
}
Home.js
export default class HomeScreen extends React.Component {
constructor(props){
super(props);
this.state={
data : []
}
}
async componentDidMount(){
this.setState({
data : await apiCall('')
})
console.log(await apiCall('?cities'))//I tried console logging to see what data I can get all I get is [Error: Request failed with status code 404] undefined
}
render() {
return (
<View>
<FlatList
keyExtractor={item => item.id}
data={this.state.data}
renderItem={({ item }) =>
<Card style={styles.container}>
<Text style={{color:'#000',fontWeight:'bold'}}>{item.categories.name} </Text>
</Card>}
/>
</View>
);
}
}
According to Zomato API documentation, in order to pull category data from a specific city you need to pass city_id as Parameter.
import React, { Component } from 'react';
import { FlatList, ActivityIndicator, Text, View } from 'react-native';
import axios from 'axios';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
data: []
}
}
async componentDidMount() {
let result;
try {
result = await axios.request({
method: 'GET',
url: "https://developers.zomato.com/api/v2.1/categories?city_id=280",
headers: {
'Content-Type': 'application/json',
'user-key': "a31bd76da32396a27b6906bf0ca707a2",
},
})
} catch (err) {
err => console.log(err)
}
this.setState({
isLoading: false,
data: result.data.categories
})
}
render() {
return (
<View>
{
this.state.isLoading ?
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator />
</View> :
<FlatList
keyExtractor={item => item.id}
data={this.state.data}
renderItem={({ item }) =>
<Text>{item.categories.name} </Text>
}
/>
}
</View>
);
}
}
Hope it helps you.

Why react-native doesn't render all content when 2 render methods included in it?

I have some content to be rendered conditionally and some fixed content i.e. footer. I dont want to render footer every time when state changes, hence I've added two methods renderContent() and renderFooter to be called in render() method.
Below code, doesn't render both methods.
'use strict';
import React, { Component } from 'react';
import { Alert, FlatList, View, StyleSheet, Text, Linking, Button } from 'react-native';
import { AsyncStorage } from 'react-native';
import getEnvVars from '../environment';
const { apiUrl } = getEnvVars();
import Moment from 'moment';
import { Ionicons } from '#expo/vector-icons';
import FootBar from '../screens/FootBar';
import { LinesLoader } from 'react-native-indicator';
export default class SubscriptionsToEnd extends Component {
static navigationOptions = ({ navigation }) => {
const { state } = navigation;
return {
title: `${state.params && state.params.title ? state.params.title : 'Subscriptions Due'}`,
};
};
constructor(props) {
super(props);
this.state = {
isLoaded: false,
dataSource: [],
title: 'Subscriptions Due'
};
}
componentDidMount() {
this._getAllCustomers();
}
_getAllCustomers() {
let url;
if (this.state.title === 'Subscriptions Due') {
url = apiUrl + "/customersWithSubscriptionNearToEnd/";
this.props.navigation.setParams({ title: 'Subscriptions Due' })
}
if (this.state.title === 'Customers') {
url = apiUrl + "/customers/";
this.props.navigation.setParams({ title: 'Customers' })
}
this.setState({ isLoaded: false })
try {
AsyncStorage.multiGet(['role', 'jwt']).then((data) => {
let role = data[0][1];
let jwt = data[1][1];
if (role === 'Admin') {
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'jwt': jwt
},
}).then(res => res.json())
.then(
(result) => {
if (result.message != 'Unauthorized user!' && this.state.title === 'Customers') {
this.setState({
isLoaded: true,
dataSource: result,
title: 'Subscriptions Due'
});
} else if (result.message != 'Unauthorized user!' && this.state.title === 'Subscriptions Due') {
this.setState({
isLoaded: true,
dataSource: result,
title: 'Customers'
});
} else if (result.message === 'Unauthorized user!') {
this.props.navigation.navigate('Login');
}
},
(error) => {
console.log(error);
this.setState({
isLoaded: true
});
this.props.navigation.navigate('Login');
}
)
}
})
} catch (error) {
console.log('Error at getting token \n' + error)
}
}
GetGridViewItem(id) {
Alert.alert(id);
}
_logOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
_addCustomer() {
// TBD
}
renderContent() {
if (!this.state.isLoaded) {
return (
<View style={styles.loader}>
<LinesLoader color='#1d91a5' barWidth={5} barHeight={60} barNumber={5} betweenSpace={5} />
</View>
)
}
if (this.state.isLoaded) {
return (
<View style={styles.container}>
<View style={styles.grid}>
<FlatList
data={this.state.dataSource}
renderItem={({ item }) =>
<View style={styles.GridViewContainer}>
<Text style={styles.GridViewTextLayout}>
<Text onPress={this.GetGridViewItem.bind(this, item._id)}>
<Text style={styles.Name}>{item.firstname}</Text> <Text style={styles.Name}>{item.lastname}</Text> {"\n"}
<Text>{Moment(item.till_date).format('Do MMM YYYY')} </Text>{"\n\n"}
</Text>
<Text onPress={() => { Linking.openURL('tel:+44' + item.mobile); }}><Ionicons name="md-phone-portrait" size={22} color="#1d91a5" /> {item.mobile}</Text> {"\n\n"}
<Text><Ionicons name="md-mail" size={22} color="#1d91a5" />{item.email}</Text>
</Text>
</View>}
numColumns={2}
keyExtractor={(item, index) => index.toString()}
/>
</View >
</View>
)
};
}
renderFooter() {
return (
<View style={styles.buttonsContainer}>
<View style={styles.button}>
<Button color='#1d91a5' title={this.state.title} onPress={this._getAllCustomers.bind(this)} />
</View>
<View style={styles.button}>
<Button color='#1d91a5' title="+Customer" onPress={this._addCustomer.bind(this)} />
</View>
<View style={styles.button}>
<Button color='#1d91a5' title="Logout" onPress={this._logOutAsync.bind(this)} />
</View>
</View>
);
}
render() {
return (
this.renderContent(),
this.renderFooter()
);
}
}
Above code only renders this.renderFooter() method. If I swap methods in render(), it renders this.renderContent().
Can someone please tell me why it is failing to render both?
I was doing it wrong. Main render() method should be like:
render() {
return (
<View style={styles.wrapper}>
{this.renderContent()}
{this.renderFooter()}
</View>
);
}
It looks like you figured it out just before I could post my answer.
The return function can only return one view. Your 2 functions each return a view. So wrapping both functions in a single view solves the problem.

Exporting JSON from fetch in React Native

I am working on exporting the JSON I get from a fetch. I know I have a binding issue, but I'm not completely sure on how I should proceed to bind my function to the current component. I have a quick example at this URL https://snack.expo.io/#mcmillster/c21pbG.
app.js
import React from 'react';
import { FlatList, ActivityIndicator, Text, View } from 'react-native';
import { getMovies } from './utility.js';
export default class FetchExample extends React.Component {
constructor(props){
super(props);
this.state ={
isLoading: true,
}
this.getMovies = getMovies.bind(this)
}
componentDidMount(){
this.getMovies;
}
render(){
if(this.state.isLoading){
return(
<View style={{flex: 1, padding: 100}}>
<ActivityIndicator/>
</View>
)
}
return(
<View style={{flex: 1, paddingTop:20}}>
<FlatList
data={ this.state.data }
renderItem={({item}) => <Text>{item.title}, {item.releaseYear}
</Text>}
keyExtractor={({id}, index) => id}
/>
</View>
);
}
}
utility.js
export function getMovies() {
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
data: responseJson.movies,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
I think you should not try to set the state from your fetch function. Just call it, return data and handle them in your component.
app.js
[...]
private getMovies = async() => {
const movies = await getMovies();
if(movies){
this.setState({...})
}
componentDidMount(){
this.getMovies();
}
utility.js
export function getMovies() {
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) =>{
console.error(error);
return;
});
}
In your componentDidMount lifecycle hook, you're not calling the getMovies function, you're just referencing it. Change this.getMovies to this.getMovies()
Solution
componentDidMount(){
this.getMovies();
}

Getting Element type is Invalid

am using react native API to display data in to FlatList and unfortunately getting below error:
Error : Element type is invalid: expected a string.
So far I have done as below:
import React, { Component } from "react";
import { View, Text, FlatList,List } from "react-native";
// import {Row} from './Row';
export default class FlatListDemo extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
page: 1,
seed: 1,
error: null,
refreshing: false,
};
}
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteRequest = () => {
const { page, seed } = this.state;
const url = `https://randomuser.me/api/?seed=${seed}&page=${page}&results=20`;
this.setState({ loading: true });
fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
data: page === 1 ? res.results : [...this.state.data, ...res.results],
error: res.error || null,
loading: false,
refreshing: false
});
})
.catch(error => {
this.setState({ error, loading: false });
});
};
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<List>
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<ListItem
roundAvatar
title={`${item.name.first} ${item.name.last}`}
subtitle={item.email}
avatar={{ uri: item.picture.thumbnail }}
/>
)}
keyExtractor={item => item.email}
/>
</List>
</View>
);
}
}
So, I have tried resolving from last two hours but stacked there. What might be the issue?
Remove List Component from Your Code and Try.