How to display fetched data in react native - 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);
});
}

Related

how to refresh the list after submitting a form in react-native?

when redirecting to index screen after submitting a post-form, the index screen does not show the newly added item in the list, can anyone help?
here is my Customer.js page
export default function Customer({ navigation }) {
const [customers, setCustomers] = useState([]);
const [isLoading, setLoading] = useState(true);
const getCustomers = async () => {
try {
const response = await fetch("http://localhost:3001/api/customers");
const json = await response.json();
setCustomers(json);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
getCustomers();
}, []);
return (
<View style={styles.item}>
<TouchableOpacity
onPress={() => navigation.navigate("AddCustomer")}
style={styles.btn}
>
<Text style={styles.btnText}>Add New Customer</Text>
</TouchableOpacity>
<FlatList
data={customers}
extraData={customers}
renderItem={({ item }) => (
<TouchableOpacity
onPress={() => navigation.navigate("CustomerDetails", item)}
>
<Text style={styles.item}>{item.name}</Text>
</TouchableOpacity>
)}
keyExtractor={(item) => item._id}
/>
</View>
);
}
}
and here is my AddCustomer.js page
const AddCustomer = ({ navigation, route }) => {
const [name, setName] = useState("");
const [phone, setPhone] = useState(0);
const [isGold, setIsGold] = useState(false);
const handleSubmit = async () => {
// e.preventDefault();
return await fetch("http://localhost:3001/api/customers", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: name,
phone: phone,
isGold: isGold,
}),
}).then(() => {
navigation.navigate("Customer", { customers: [name, phone, isGold] });
});
};
return (
<View>
<Text style={styles.title}>Add New Customer</Text>
<View>
<TextInput
style={styles.input}
onChangeText={(val) => setName(val)}
value={name}
placeholder="Your name"
onBlur={Keyboard.dismiss}
/>
<TextInput
style={styles.input}
onChangeText={(val) => setPhone(val)}
value={phone}
placeholder="phone number"
/>
<TextInput
style={styles.input}
onChangeText={(val) => setIsGold(val)}
value={isGold}
placeholder="is gold member"
autoCorrect={false}
autoCapitalize={false}
/>
</View>
<View style={styles.inputContainer}>
<TouchableOpacity style={styles.saveButton} onPress={handleSubmit}>
<Text style={styles.saveButtonText}>Add Customer</Text>
</TouchableOpacity>
</View>
</View>
);
};
new customer would be added and everything else work fine but the Customer page does not get re-rendered or refresh or reload.
In your Customer.js do it like below -
useEffect(() => {
const unsubscribe = navigation.addListener('focus', async () => {
getCustomers();
});
return unsubscribe ;
}, [navigation]);
import { useFocusEffect } from '#react-navigation/native';
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
getCustomers();
return () => {
// Do something when the screen is unfocused
};
}, []),
);

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>

Refresh data in 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.

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