Handling JSON response React Native - json

I'm following the React Native documentation for fetching JSON from an API (https://reactnative.dev/docs/network). I'm new to react and wanting to fetch a wordpress list of posts through its API, but the example they use is very simple and structured differently to how the object is returned from WP.
The problem I'm having is that it is returning the JSON, but I'm unsure how to reference each item I want to display in my flatlist. The line of problem is;
.then((json) => setData(json.movies))
For this WP returned JSON, there is no movies (obviously), in the absence of a referable point what would I specify instead?
My code;
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
export default App = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://public-api.wordpress.com/wp/v2/sites/derbyfutsal.com/posts')
.then((response) => response.json())
.then((json) => setData(json.movies))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text>{item.title}, {item.excerpt}</Text>
)}
/>
)}
</View>
);
};

You dont have to specify anything, you can directly set the response to the state value and use it in the flatlist.
I've updated the code to display the id instead of title as its an object. You can change it anyway you want and use it.
const App = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://public-api.wordpress.com/wp/v2/sites/derbyfutsal.com/posts')
.then((response) => response.json())
.then((json) => {
setData(json)
})
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text>{item.id}</Text>
)}
/>
)}
</View>
);
};

Related

I can't display the data from an API into a FlatList, but I see it in my console.log. What is the problem?

Console logging my react native app shows the data I fetch from an API. The problem now is that it is not displaying in the FlatList.
const HealthLinkMain = () => {
const [data, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get(API_URL, {
method: "GET",
headers: {
Authorization: `Bearer ${TOKEN}`,
},
});
setData(response.data)
} catch (error) {
console.error(error);
}
};
fetchData();
}, []);
return (
<View style={styles.container}>
<Text>Test</Text>
<FlatList
data={data.data}
renderItem={(item) => (
<View>
<Text>{item.clinic_name}</Text>
<Text>{item.clinic_address}</Text>
</View>
)}
keyExtractor={(item, index) => item.clinic_name}
/>
</View>
);
};
I think the problem might be in your renderItem as you haven't destructured the item, try this:
renderItem = {({ item }) => {
return (
<View>
<Text>{item.clinic_name}</Text>
<Text>{item.clinic_address}</Text>
</View>
)
}}
You can also seperate it the renderItem into a function of it's own which a lot of people tend to do:
const renderItem = ({item}) => {
return(
<View>
<Text>{item.clinic_name}</Text>
<Text>{item.clinic_address}</Text>
</View>
)
}
and then change the flatlist calling function accordingly:
<FlatList
data={data.data}
renderItem={renderItem}
keyExtractor={(item, index) => item.clinic_name}
/>

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.

FlatList receiving undefined values after fetching json

I need to render a FlatList after fetching a json containing connections. The following piece of code runs correctly but the travel object inside the renderItem is always undefined.
import {Text, View, FlatList, ActivityIndicator} from 'react-native';
import React, {useEffect, useState} from 'react';
/**
* http://transport.opendata.ch/v1/connections?from=8575201&to=8503000
*/
export function TravelsScreen({navigation}) {
const [isLoading, setLoading] = useState(true);
const [travels, setTravels] = useState([]);
useEffect(() => {
fetch('http://transport.opendata.ch/v1/connections?from=8575201&to=8503000')
.then(response => response.json())
.then(json => setTravels(json.connections))
.catch(error => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<View style={{flex: 1, padding: 24}}>
{isLoading ? (
<ActivityIndicator />
) : (
<FlatList
data={travels}
renderItem={({travel}) => <Text>Travel: {console.log(travel)}</Text>}
keyExtractor={travel => travel.from.departureTimestamp.toString()}
/>
)}
</View>
);
}
Please update your FlatList to :
<FlatList
data={travels}
renderItem={({item}) => {console.log(item)}}
//other properties
/>
From official documentation the renderItem method takes out item from the FlatList array and since you are using the destructuring syntax to extract it, you should explicitly use item. An alternative without the destructuring syntax would look like :
<FlatList
data={travels}
renderItem={(travel) =>{ console.log(travel.item)}}
//other properties
/>

How can i solve uniqe key prop problem in React native

I have React Native project and when i try to build my phone, i'm getting this error message. Warning: Each child in an array or iterator should have a unique "key" prop. But it works on computer emulator.
Here is json data: http://hazir.net/api/match/today
and here is my codes,
import React from 'react';
import { FlatList, ActivityIndicator, Text, View } from 'react-native';
export default class Matches extends React.Component {
constructor(props){
super(props);
this.state ={ isLoading: true}
}
componentDidMount(){
return fetch('http://hazir.net/api/match/today')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson,
}, 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.matchId}, {item.matchDate}</Text>}
keyExtractor={({id}, index) => id}
/>
</View>
);
}
}
The easiest solution would be to update your keyExtractor as it appears to not be working. It doesn't look like your data has an id property, however it does have a matchId property. This means you could do something like the following.
<FlatList
...
keyExtractor={({matchId}, index) => matchId.toString()}
/>
Alternatively you could use the index as the key and do this
<FlatList
...
keyExtractor={({matchId}, index) => index.toString()}
/>

FlatList Onpress show page with json data for each user

I have a endusers page where I fetch from an api and how the results in a flatlist as listitem.
I want to have one page for each user which shows their info but without creating userX.js for each user. So there should be only 1 page which is dynamically.
My Endusers.js View:
return (
<View style={styles.container}>
<View style={styles.headerContainer}>
<SearchBar
showLoading
placeholder={`Suchen: Name, Email oder Land...`}
lightTheme
round
onChangeText={text => this.searchFilterFunction(text)} />
</View>
<View style={styles.listContainer}>
<FlatList
style={styles.list}
data={this.state.data}
renderItem={({ item }) =>
<ListItem
titleStyle={styles.item}
subtitleStyle={styles.item}
title={`${item.strName} | ${item.strLand}`}
subtitle={`${item.strEmail}`}
containerStyle={{ borderBottomWidth: 0 }}
onPress={() => this.props.navigation.push('Userpage')}
/>}
keyExtractor={id => id}
/>
</View>
</View>
)
My Fetch method:
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
data: upper(responseJson.sort((a, b) => (a.strName - b.strName))),
loading: false,
error: responseJson.error
})
this.searchArray = responseJson;
})
.catch((error) => {
console.log(error)
})
My Constructor:
constructor() {
super()
this.state = {
loading: true,
data: [],
error: null
}
this.searchArray = [];
}
In Endusers.js View when I click on listitem the Userpage.js should show with the info of the clicked user.
How should I go on about this problem? What are the keywords I need to
google/research to find a solution? I'm not her to just copy paste so
please don't get this question wrong^^
You can send params when you push the navigation:
this.props.navigator.push({
component: MyScene,
title: 'Scene ' + nextIndex,
passProps: {index: nextIndex},
});
You can send as passProps your item which i guess contains the details regarding your User, like this:
passProps: {item: item}
Hope I helped, and more details on react-native documentation https://facebook.github.io/react-native/docs/navigation.