Refresh data in react-native - react-native

Hi so I want to refresh data when I pull down but I'm not sure about how to do it. Here is my code :
async componentDidMount() {
this.getData();
}
async getData(){
const url = "SomeUrl";
await fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
dataSource: res
});
})
.catch(error => {
console.log("get data error:" + error);
});
}
<SafeAreaView style={{ flex:1 }}>
<View style={styles.main_container}>
<FlatList style={styles.flatList}
data={this.state.dataSource}
extraData = {this.state}
keyExtractor={(item, index) => item.MembreId}
renderItem={(item) => <UserItem user={item} displayDetailForUser={this._displayDetailForUser} />}
numColumns={numColumns}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh} />
</View>
</SafeAreaView>
So here I'm getting the data in dataSource. I have tried this but it's loading endlessly.. And do I also need to wipe the previous data in dataSource first or not ?
handleRefresh = () => {
this.setState (
{
refreshing: true,
},
() => {
setTimeout(() => {this.getData()}, 1000)
}
);
};

It looks like you are not setting the refreshing back to false once the data comes back. Try this for getData:
async getData(){
const url = "SomeUrl";
await fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
dataSource: res,
refreshing: false,
});
})
.catch(error => {
console.log("get data error:" + error);
});
}

Try setting refreshing state to false in this.getData() with dataSource.

Related

Warning: Each child in a list should have a unique "key" prop. React Native

Hello i'm trying to build a mini social media app with react native, getting the following error:
Warning: Each child in a list should have a unique "key" prop.
Check the render method of VirtualizedList
tried to use results.map instead of flat list also.
and also to change the key extractor with solutions on stackoverflow, but no success.
anyone can help please ?
code:
return (
<FlatList
style={{flex:1}}
data={results}
keyExtractor={(item, index) => {
return item.id;
}}
renderItem={({item}) => <TouristCard key={item.id} item={item} onPress={()=> navigation.navigate('HomeProfile', {userId: item.userId})} /> }
/>
);
TouristCard:
const TouristCard = ({item,onPress}) => {
return (
<View key={item.id} style={styles.listItem} >
<UserImg source={{uri: item.userImg ? item.userImg : 'https://lh5.googleusercontent.com/-b0PKyNuQv5s/AAAAAAAAAAI/AAAAAAAAAAA/AMZuuclxAM4M1SCBGAO7Rp-QP6zgBEUkOQ/s96-c/photo.jpg'}}/>
<View style={{alignItems:"center",flex:1}}>
<Text style={{fontWeight:"bold"}}>{item.fname ? item.fname : 'Annonymous' } {item.lname ? item.lname : '' }</Text>
<Text>{item.flightDesc}</Text>
<Text style={{fontWeight:"bold"}}>{item.age}</Text>
</View>
<Text style={{color:"blue"}}>View Profile</Text>
</View>
);
results object:
const filterByDates = (results,startDate,endDate) => {
return results.filter(res => {
return startDate<res.endDate && res.startDate<endDate;
});
};
useEffect(() => {
const fetchCommunity = async() => {
try {
//const list = [];
await firestore()
.collection('flights')
.where("destination","==",destination)
.where("user","!=",user.uid)
.get()
.then((querySnapShot) => {
querySnapShot.forEach(doc => {
const {user,flightDesc,startDate,endDate} = doc.data();
list.push({
user: user,
flightDesc,
startDate,
endDate
});
})
})
setResults(filterByDates(list,startDate,endDate));
fetchProfiles();
} catch(e) {
console.log(e);
}
}
const fetchProfiles = async() => {
try {
//const list2=[];
list.forEach(async obj => {
await firestore()
.collection('users')
.where("userId","==",obj.user)
.get()
.then((querySnapShot) => {
querySnapShot.forEach(doc => {
const {userImg,age,fname,lname} = doc.data();
list.push({
id: doc.id,
userImg,
age,
fname,
lname
});
})
})
setResults(list);
console.log(list);
})
} catch (e) {
console.log(e);
}
}
fetchCommunity();
},[]);
Replace your Flatlist with this.
<FlatList
style={{flex:1}}
data={results}
keyExtractor={(item) => item.id.toString()} // Here was the error
renderItem={({item}) => <TouristCard item={item} onPress={()=> navigation.navigate('HomeProfile', {userId: item.userId})} /> }
/>
Also check whether each element of your results has a unique id or not?
And MAIN point... Check does your array items has a property called id or not..and if userId is unique then use that as shown above

Trying to get result from more than one api React native in the same page

i m trying to get data from database and put it inside a picker when i use one fecth it work fine but when i add the second one it get an error says " typeError: undefined is not an object (evaluating 'this.state.dataSource2.map') "
componentDidMount() {
fetch('url1')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson,
}
);
})
.then( () => {
fetch('url2')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource2: responseJson
});
})
})
.catch((error) => {
console.error(error);
});
}
first picker :
onValueChange={(itemValue, itemIndex) => this.setState({ar1: itemValue})} >
{ this.state.dataSource.map((item, key)=>(
<Picker.Item label={item.nom} value={item.nom} key={key} />)
)}
</Picker>
second picker :
onValueChange={(itemValue, itemIndex) => this.setState({ar2: itemValue})} >
{ this.state.dataSource2.map((item, key)=>(
<Picker.Item label={item.nom} value={item.nom} key={key} />)
)}
</Picker>

How to display fetched data in react native

I successfully posted data in MongoDB Atlas, Now i want to display that data in my simple react native App. Data is showing in my terminal but i am not able to display data in my App.
Here is code for Get data form the db.
display(){
fetch('myUrl', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
title: responseJson,
description: responseJson
})
})
.catch((error) => {
console.error(error);
});
}
Here is the code that is not displaying the data in App
<TouchableOpacity onPress={()=>this.display()} style={styles.btn}>
<Text style={{textAlign: 'center'}}> Display </Text>
</TouchableOpacity>
<View>
<FlatList
data={this.state.title}
renderItem={({item}) => <Text>{item.title}</Text>}
keyExtractor={({id}, index) => id}
/>
</View>
Flatlist data property expects an array.
But you seem to set an object.
If your api returns an array you can make the following changes to make it work:
state = {
items:[]
}
display() {
fetch('myUrl', { method: 'GET'})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
items: responseJson
})
})
.catch((error) => {
console.error(error);
});
}
As you see I used items in state as array, and updated its value when I got response from api.
And in flatlist:
<View>
<FlatList
data={this.state.items}
renderItem={({item}) => <Text key={item._id}>{item.title}</Text>}
keyExtractor={ item => item._id}
/>
</View>
A sample codesandbox
Update your code like this:
this.state = {
responseData:[]
}
display = () => {
fetch('myUrl', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
responseData: responseJson,
})
})
.catch((error) => {
console.error(error);
});
}
inside your render function:
render(){
const { responseData } = this.state;
return(
<TouchableOpacity onPress={()=>this.display} style={styles.btn}>
<Text style={{textAlign: 'center'}}> Display </Text>
</TouchableOpacity>
<View>
<FlatList
data={responseData}
renderItem={this.renderItem}
keyExtractor={item => item.id}
/>
</View>
);
}
renderItem = ({item}) => {
const { title, id, description, date } = item;
<View key={item.id}>
<Text>{item.id}</Text>
<Text>{item.title}</Text>
<Text>{item.description}</Text>
<Text>{item.date}</Text>
</View>
}
try with return keywork
Working demo api
display(){
return fetch('myUrl', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
title: responseJson,
description: responseJson
})
})
.catch((error) => {
console.error(error);
});
}

FlatList does not scrolls down but retracts back to top

After scrolling, flatlist goes back to the top. Any obvious reason this might be happening because of my code?
react-native-cli: 2.0.1
react-native: 0.57.4
FlatList Code
return (
<View style={{ flex: 1}}>
<FlatList
data={this.state.dataSource}
onEndReached = {() => this.getDeals()}
ListHeaderComponent = {() => <MainAdvertisement/>}
onEndReachedThreshold={1}
renderItem={this._renderItem}
ListFooterComponent={()=>((this.state.loading || this.state.loading=="")&&!this.state.gotAllDeals) ? <ActivityIndicator size="small" color="gray"/> : null}
keyExtractor={(item, index) => item._id}
/>
</View>
);
getDeals()
This is the function called when end of Flatlist is reached.
getDeals = () => {
this.setState({
loading: true,
});
let url = this.state.url;
let offsetEncoded = encodeURIComponent(this.state.offset);
url=url+"offSet="+offsetEncoded+"&&filters="+JSON.stringify(this.props.filters);
console.log(url);
fetch(url)
.then((res)=>{
if (!res.ok) {
throw Error(res.statusText);
}
return res;
})
.then((res) => res.json())
.then((responseJson) => {
if(responseJson.length==0){
this.setState({
gotAllDeals:true,
loading:false
})
}
else{
this.setState({
loading: false,
dataSource: this.state.offset==0 ? responseJson : [...this.state.dataSource, ...responseJson],
offset: this.state.offset + responseJson.length,
dealList_ErrorStatus: false
});
}
})
.catch((err) => {
this.setState({
dealList_ErrorStatus: true,
loading:false
})
console.log("Error: "+err);
});
}
ScreenRecording

React Native JSON Filtering

I'm in the learning process of React Native and working on filtering through a JSON feed. I am able to filter down to a group of data, but I am looking to filter further within that group. At "filteredItem" I am able to get the example below.
{"$id":"3","num":256,"event":"1234","description":"example description","startdate":"2018","enddate":"2019"}
If I wanted to filter down to the event number similar to how I am displaying the whole group of info how would I do that?
componentDidMount() {
return fetch('myurl')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
filteredItem: responseJson.filter(item => item.$id == 3),
}, function () {
});
})
.catch((error) => {
console.error(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator />
</View>
)
}
return (
<View>
<Text>
{JSON.stringify(this.state.filteredItem, null, 2)}
</Text>
</View>)
}
}
This will filter item $id == 3 and item event == 1234.
filteredItem: responseJson.filter(item => item.$id == 3 && item.event == 1234)
You can play around with responseJson to achieve what array you want.
componentDidMount() {
return fetch('myurl')
.then((response) => response.json())
.then((responseJson) => {
// Put logic to process the responseJson here before setState
console.log(responseJson)
let filteredResponseJson = responseJson.filter(item => item.$id == 3)
console.log(filteredResponseJson)
this.setState({
isLoading: false,
filteredItem: filteredResponseJson,
})
})
.catch((error) => {
console.error(error);
});
}
Update your text like this
<Text>
{this.state.filteredItem.map(item=>item.id)}
</Text>
Change the item.id to which ever prop you want