I have this issue undefined is not an object (evaluating 'this.state.dataSource.map') - json

I want to display a list of places from a online json url.
import React, { Component } from "react";
import {
View,
StyleSheet,
Dimensions,
Image,
StatusBar,
TextInput,
TouchableOpacity,
Text,
Button,
Platform,
Alert,
FlatList,
ActivityIndicator,
} from "react-native";
let url = "https://cz2006api.herokuapp.com/api/getAll";
let url2 = "";
export default class ClinicComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
};
}
componentDidMount() {
return fetch("https://cz2006api.herokuapp.com/api/getAll")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data.data,
});
})
.catch((error) => {
console.log(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
} else {
let hospitals = this.state.dataSource.map((val, key) => {
return (
<View key={key} style={styles.item}>
<Text>{val.name}</Text>
</View>
);
});
return (
<View style={styles.item}>
{/* <Text>Content Loaded</Text> */}
{hospitals}
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
item: {
flex: 1,
alignSelf: "stretch",
margin: 10,
alignItems: "center",
justifyContent: "center",
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
});
Unfortunately when i tried to run this via expo cli I got an error, saying undefined is not an object
enter image description here
Can anyone help me pls!!! I would just like to have a list of hospitals which are scrollable. Thank you!
The URL of the Json is here: https://cz2006api.herokuapp.com/api/getAll

Simply change your initial state to something like this
this.state = {
isLoading: true,
dataSource: [], // <-- here
};
Your problem is you're using dataSource.map but during api calling your dataSource still stay null until it get its response, and null object have no attribute map. That's the cause of your problem.

remove the return in componentDidMount:
componentDidMount() {
fetch("https://cz2006api.herokuapp.com/api/getAll")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.data.data,
isLoading: false,
});
})
.catch((error) => {
console.log(error);
});
}

I agree with #Nguyễn's suggestion that your initial state should be an array. However the root of the issue seems to be getting the right properties off off your JSON response.
First, you want responseJson.data instead of responseJson.data.data. That gives me an array and shows a long list but the titles are all blank. That's because your response has Name as an uppercase property but you are accessing name. So you need to change that as well.
export default class ClinicComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
};
}
componentDidMount() {
return fetch('https://cz2006api.herokuapp.com/api/getAll')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
});
})
.catch((error) => {
console.log(error);
});
}
render() {
//console.log(this.state.dataSource?.[0]);
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
} else {
return (
<View style={styles.item}>
{/* <Text>Content Loaded</Text> */}
{this.state.dataSource.map((val, key) => (
<View key={val._id} style={styles.item}>
<Text>{val.Name}</Text>
</View>
))}
</View>
);
}
}
}
You are fetching a huge amount of data and you probably want some sort of pagination with infinite scrolling. It is extremely slow to load due to the huge payload that we are fetching.
You also have double-escape problem in the JSON response inside the geocodingData section. You want to return this data as an object but it is an escaped string with lots of \" instead.

Related

Invalid attempt to spread non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method. in my app

i tried to show search result feature by using flatlist (json API) and search bar in my code, but i found this error and can't solve it. I can run the search but can't display the search results, can anyone help me solve this error, because this is for my college assignment
this is my code
import {
Box,
Text,
Image,
Heading,
Center,
ScrollView,
Spinner,
FlatList,
Pressable,
View,
Stack,
} from 'native-base';
import React, { Component } from 'react';
import { Dimensions } from 'react-native';
import { ListItem, SearchBar } from '#rneui/themed';
const windowWidth = Dimensions.get('window').width;
class Ilegal extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true,
isFetching: false,
searchTxt: null,
error: null,
temp: [],
};
};
async getData() {
try {
const response = await fetch(
'https://ojk-invest-api.vercel.app/api/illegals'
);
const json = await response.json();
this.setState({ data: json.data.illegals });
this.setResult(json);
} catch (error) {
console.error(error);
} finally {
this.setState({
isLoading: false,
isFetching: false,
});
}
};
setResult = (res) => {
this.setState ({
data: [...this.state.data, ...res],
temp: [...this.state.temp, ...res],
error: res.error || null,
isLoading: false,
});
};
renderHeader = () => {
return <SearchBar placeholder='Cari Perusahaan..'
lightTheme round editable={true}
value={this.state.searchTxt}
onChangeText={this.updateSearch}
/>
};
updateSearch = searchTxt => {
this.setState({searchTxt}, () => {
if ('' == searchTxt) {
this.setState({
data: [...this.state.temp],
});
return;
}
this.state.data = this.state.temp.filter(function (item) {
return item.name.includes(searchTxt);
}).map(function({ id, name, type }) {
return {id, name, type};
});
});
};
componentDidMount() {
this.getData();
};
onRefresh = () => {
this.setState({ isFetching: true }, () => {
this.getData();
});
};
renderItem = ({ item }) => {
const { navigation } = this.props;
return (
<>
<Pressable
style={{ padding: 20, backgroundColor: 'white' }}
onPress={() => navigation.navigate('Detail Ilegal', { data: item })}>
<Center>
<View
style={{
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text
style={{
fontSize: 16,
width: windowWidth - 40,
textAlign: 'justify',
marginTop: 6,
}}>
{item.name}
</Text>
<Text
style={{
color: '#808080',
fontSize: 14,
width: windowWidth - 40,
textAlign: 'justify',
marginTop: 6,
}}>
{item.type}
</Text>
</View>
</Center>
</Pressable>
<View style={{ borderWidth: 0.5, borderColor: '#cccccc' }}></View>
</>
);
};
render() {
const { data, isLoading, isFetching, error} = this.state;
return (
<View style={{ flex:1, justifyContent:'center', backgroundColor:'white', flexDirection: 'column', }}>
{isLoading ? (
<Spinner size="large" color="#AA0002" />
) : (
<FlatList
ListHeaderComponent={this.renderHeader}
data={data}
keyExtractor={({ link }, index) => link}
renderItem={this.renderItem}
onRefresh={this.onRefresh}
refreshing={isFetching}
/>
)}
</View>
);
}
}
export default Ilegal;
you can help me for fixed this error ?
I think the error is in setResult() function as far as I could understood your set result function. You are setting data like this
this.setState({ data: json.data.illegals });
in getData() while you are fetching data from API but you are sending json as parameter to setResult which is object. Try to change your setResult() as below:
setResult = (res) => {
this.setState ({
data: [...this.state.data, ...res.data.illegals],
temp: [...this.state.temp, ...res.data.illegals],
error: res.error || null,
isLoading: false,
});
};

show a list of data in react native app from sql server

I wanted to show a list of data in my app, I already have backend API that can get the data from the server but when I trying to make it appear in my react native app, it wont appear. Below is the data that get from API
here is the code for show the data in a list view in react native apps
import React, { useState, useEffect,Component,onMount} from 'react';
import {View,Text, Button, StyleSheet,TextInput,ListView,ActivityIndicator,Platform} from 'react-native';
import {useNavigation} from'#react-navigation/native';
import {StatusBar} from'expo-status-bar';
export default function StopJob(){
const[isLoading,setIsLoading]=useState(true);
useEffect(()=>{
return fetch('http://localhost/api/findid.php',{
mode:'no-cors'
})
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2)=> r1 !== r2});
this.setState({
isLoading: false,
dataSource: ds.cloneWithRows(responseJson),
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
})
},[]);
const Showlist=(user,job,jobid,machinecode,startTime)=>{
this.props.navigation.navigate('Third', {
Userid : user,
Job : job,
JobId : jobid,
MachineCode : machinecode,
StartTime : startTime
});
}
const ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
if(isLoading)return(<View style={{flex: 1, paddingTop: 20}}><ActivityIndicator /> </View>);
return(
<View style={styles.MainContainer_For_Show_StudentList_Activity}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={ (rowData) => <Text style={styles.rowViewContainer}
onPress={this.Showlist.bind(
this, rowData.user,
rowData.job,
rowData.jobid,
rowData.machinecode,
rowData.startTime
)} >
{rowData.job}
</Text> }
/>
</View>
);
}
const styles = StyleSheet.create({
MainContainer_For_Show_StudentList_Activity :{
flex:1,
paddingTop: (Platform.OS == 'ios') ? 20 : 0,
marginLeft: 5,
marginRight: 5
},
rowViewContainer: {
fontSize: 20,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10,
}
});
the expected output will only show the job from the database, but for now the function did not show the list view the error shown Text strings must be rendered within a component.
I was referring this webpage to implement the code : https://reactnativecode.com/insert-update-display-delete-crud-operations/
on the example it show function well but when I try to implement it, it cant work :(
updated but still having same error
export default function StopJob(){
const[isLoading,setIsLoading]=useState(true);
const[dataSource,setdataSource]=useState();
useEffect(()=>{
return fetch('http://localhost/api/findid.php')
.then((response) => response.json())
.then((responseJson) => {
let ds = new FlatList.DataSource({rowHasChanged: (r1, r2)=> r1 !== r2});
setIsLoading(false)
setdataSource(ds.cloneWithRows(responseJson))
})
.catch((error) => {
console.error(error);
})
},[]);
const Showlist=(user,job,jobid,machinecode,startTime)=>{
this.props.navigation.navigate('', {
Userid : user,
Job : job,
JobId : jobid,
MachineCode : machinecode,
StartTime : startTime
});
}
const ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
if(isLoading)return(<View style={{flex: 1, paddingTop: 20}}><ActivityIndicator /> </View>);
return(
<View style={styles.MainContainer_For_Show_StudentList_Activity}>
<FlatList
dataSource={dataSource}
keyExtractor={item=>item.user}
ItemSeparatorComponent= {ListViewItemSeparator()}
renderItem={ (item) => <Text style={styles.rowViewContainer}>{item.job}</Text> }
/>
</View>
);
}
Ok here are the steps to follow:
Use flatlist
Your data source should be a regular array. So, you can use the response from your api as it is.
renderRow should change as renderItem
renderSeparator should change as ItemSeparatorComponent
here is the final form:
const[isLoading,setIsLoading]=useState(true);
const [data, setData]=useState([]);
.......
fetch('http://localhost/api/findid.php',{
mode:'no-cors'
})
.then((response) => response.json())
.then((responseJson) => {
//you can't use setState inside function components. :)
setData(responseJson);
setLoading(false);
})
.catch((error) => {
console.error(error);
})
.......
<FlatList
data={data}
keyExtractor={item => item.jobid} //it should be unique. change it
renderItem={({item}) => <Text>{item.job}</Text>}
/>
This should solve your issue for now but keep in mind these too:
Looks like you don't know differences between class components and function components. Do your research
Flatlist has it's own performance configurations. Research and implement them.

React Native Unexpected token < in JSON at position 0

I am trying to view JSON data downloaded but receiving Unexpected token < in JSON at position 0. The error code is not helping at all. If I access the JSON using browser, I don't see a problem. It somehow giving error during parsing. Can someone give any suggestions ?
export default class CategoryScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
datasource: null,
}
}
componentDidMount(){
return fetch('http://xhunterx.ezyro.com/a-cnn.json')
.then((response) => response.json() )
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.movies,
})
})
.catch((error) => {
console.log(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View>
<ActivityIndicator />
</View>
)
} else {
let news = this.state.dataSource.map((val, key) => {
return <View key={key} style={styles.item}>
<Text style={styles.item}>{val.title}</Text>
</View>
});
return (
<View>
{news}
</View>
);
}
Issue is in this line
dataSource: responseJson.movies
You are having an array directly in responseJson, not inside movies. Try with
dataSource: responseJson

Trying to display JSON Data, but receiving JSON Parse Error

I am trying to display JSON data on my screen, the integer 4 to be exact.
But, I am receiving a JSON Parse Error.
I've posted and that works fine as in Webhooksite says it successfully posted. Also, it "gets" fine, but the data doesn't display. Please help!
// JSON Data
{
"cheetosamount": 4,
"cookiesvalue": 2
}
export default class ChooseDeliveries extends Component {
constructor(props){
super(props);
this.state = {
isLoading: true,
dataSource: null
}
}
componentDidMount(){
this.handleGetRequest();
}
handleGetRequest() {
fetch ('https://webhook.site/e61dd236-92d5-4b3b-882b-a50d6add6cd3',{
method: 'GET',
})
.then(response => response.json())
.then(responseJson => {
this.setState({
dataSource: JSON.parse(responseJson),
isLoading: false,
})
})
.catch(error => {
console.error(error);
});
};
render(){
if(this.state.isLoading){
return(
<View style={{flex: 1, padding: 20}}>
<ActivityIndicator/>
</View>
)
} else {
return(
<View style={{flex: 1, paddingTop:20}}>
<Text>
{this.state.dataSource.cheetosamount}
</Text>
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
I believe its because that 'JSON' that you are getting is already an object and there's no need for you to parse it.
More indepth explaination provided here SyntaxError: Unexpected token o in JSON at position 1
Try the following in your chrome console
let c ={
"cheetosamount": 4,
"cookiesvalue": 2
}
c.cheetosAmount
So essentially all you have to do is
this.setState({
dataSource: responseJson,
isLoading: false,
})

React Native How to store and process JSON data?

I am a total beginner in React Native programming. I've had a difficulty finding a tutorial explaining how to do this.
I am fetching a bus schedule data from a web API.
I want to do the following.
Store JSON data inside a variable or something.
Run a function on that JSON data to return appropriate bus data
I have two questions regarding this.
How can I store JSON data inside a variable or locally somehow?
If I want to run a JavaScript function on the JSON data, where do I do it? Inside a separate component's render() function?
What I've tried
I declared let jsondata outside of the class.
Inside componentDidMount I stored responseJson to jsondata using an anonymous function. When I console.log it there, it shows the JSON data properly.
However, when I try to {console.log(jsondata)} after Flatlist, it returns undefined while "Hello" logs correctly.
Why is it behaving this way? How can I use the jsondata?
Code
import React from 'react';
import { FlatList, ActivityIndicator, Text, View } from 'react-native';
let jsondata;
export default class FetchExample extends React.Component {
constructor(props){
super(props);
this.state ={ isLoading: true}
}
// make an API call in the beginning
componentDidMount(){
return fetch('https://api.myjson.com/bins/18o9sd')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.shosfc.weekday[7]
}, function(){
jsondata = responseJson;
// console.log(jsondata)
});
})
.catch((error) =>{
console.error(error);
});
}
render(){
if(this.state.isLoading){
return(
<View style={{flex: 1, padding: 50}}>
<ActivityIndicator/>
</View>
)
}
return(
<View style={{flex: 1, paddingTop:50}}>
<FlatList
data={this.state.dataSource}
renderItem={({item}) => <Text>{item.min}</Text>}
// keyExtractor={({id}, index) => id}
/>
{console.log(jsondata)}
</View>
);
}
}
How can I store JSON data inside a variable or locally somehow?
You can put it in a state value, and use local storage for storage.
Status value delivery
this.state ={ jsondata:{}}
...
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.shosfc.weekday[7],
jsondata = responseJson
});
console.log(this.state.jsondata);
}
Store data locally
import {AsyncStorage} from 'react-native';
...
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.shosfc.weekday[7],
});
AsyncStorage.setItem('jsondata', JSON,stringify(responseJson));
}
If I want to run a JavaScript function on the JSON data, where do I do it? Inside a separate component's render() function?
I find this question difficult to understand. But the answer to this question I understand is that you can declare and use a function outside of JSON.
thisfunc(){
alert("function in Json")
}
...
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.shosfc.weekday[7],
});
this.thisfunc.bind(this)
}
Add jsonResponse in state try this.
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,
dataSource: [],
apiResponseJson:null
};
}
// make an API call in the beginning
componentDidMount() {
return fetch('https://api.myjson.com/bins/18o9sd')
.then(response => response.json())
.then(responseJson => {
this.setState(
{
isLoading: false,
dataSource: responseJson.shosfc.weekday[7],
apiResponseJson : responseJson.shosfc
},
);
})
.catch(error => {
console.error(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, padding: 50 }}>
<ActivityIndicator />
</View>
);
}
return (
<View style={{ flex: 1, paddingTop: 50 }}>
<FlatList
data={this.state.dataSource}
renderItem={({ item }) => <Text>{item.min}</Text>}
// keyExtractor={({id}, index) => id}
/>
{console.log(this.state.apiResponseJson)}
</View>
);
}
}