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
Related
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
I'm new in RN, so this code may be wrong.
The error is : "TypeError: undefined is not a function (near '...kanjis.map...')"
This error happen when I try to set state "setKanjis(item)", the error occurs in the return(
{kanjis.map((item) => {}
)
const [kanjis, setKanjis] = useState([]);
useEffect(() => {
fetch(URL)
.then((response) => response.json())
.then((responseJson) => {
const result = responseJson.kanjis.filter(
(item) => item.should_learn == 0,
);
setKanjis(result);
});
}, []);
kanjis.map((item) => {
return item.selected == true
? ((item.should_learn = 1), setKanjis(item))
: item.should_learn;
});
return (
<View style={styles.kanjiView}>
{kanjis.map((item) => {
return (
<View>
{item.selected == true ? (
) : (
)}
</View>
);
})}
</View>
<TouchableOpacity style={styles.addButton} onPress={addKanji}>
<Text style={styles.addButtonText}>Add</Text>
</TouchableOpacity>
);
};
What i'm doing wrong?
your backend api call and setState are both async functions, so that's why kanjis.map is returning an error. To resolve that error, you can move the map function inside the promise resolving code.
useEffect(() => {
fetch(URL)
.then((response) => response.json())
.then((responseJson) => {
const result = responseJson.kanjis.filter(
(item) => item.should_learn == 0,
);
setKanjis(result);
result.map((item) => {
return item.selected == true
? ((item.should_learn = 1), setKanjis(item))
: item.should_learn;
});
});
}, []);
please note that i changed kanjis.map to result.map reason being that setState is async. There are other things wrong with your code, so you will still see errors. For example, you are still referencing the state variable kanjis in your return
<View style={styles.kanjiView}>
{kanjis.map((item) => {
return (
<View>
{item.selected == true ? (
) : (
)}
</View>
);
})}
</View>
One way to work around that is to render a loading page (or a spinner) before the back api resolves. you simply check the state variable kanjis, if it's undefined render spinner. If it's defined render your data.
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);
});
}
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.
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