React Native -Flatlist renderItem promise - reactjs

I have a working flatlist in react native
<FlatList
data={orders}
keyExtractor={item => item._id}
renderItem={({ item }) => (renderItem(item))}
/>
I've added a new promise withing my renderItem function like :
const renderItem = (item) => {
const getRestaurant = async (id) => {
uri = 'https://xxx.xxx.xxx/api/list/xxx/' + id ;
return fetch(uri)
.then((response) => response.json())
.then((json) => {
return json;
//console.log("json=>"+json[0].name);
})
.catch((error) => {
console.error(error);
});
}
const promise = getRestaurant(item.restaurantId);
promise.then(data =>{
console.log(data[0].name)
return (
<Text>{data[0].name}</Text>
)
})}
If I do a
console.log(data[0].name)
the information i am looking for is correct but i simply cannot return that information in my flatlist to be displayed . Ive done something like :
return (
<Text>{data[0].name}</Text>
)
but nothing is being display on my flatlist !
Can anyone please help me . Thank you

You cannot use the variables directly inside the component , you need to use state.
Because when there is a change in state , react-native will render your components.
For example you can make use of useState hook
first import useState from like below
import React, { useState } from "react";
and then inside ur function
const [response, setResponse] = React.useState(false);
and then inside ur promise
promise.then(data =>{
setResponse(data[0].name)
return (
<Text>{response}</Text>
)
})}

Related

React cant fetch data from API

I want to fetch data from given API(link is censored in code example), but cant manage to to display product.name from my Api fetch.
import { useState, useEffect } from "react";
import axios from "axios";
function DataFetching() {
const [posts, setPosts] = useState([]);
useEffect(() => {
axios
.get("https://CENSORED/")
.then((res) => {
console.log(res);
setPosts(res.data);
})
.catch((err) => {
console.log(err);
});
}, []);
return (
<div>
<div>
{posts.map((post) => (
<h1>{post.product.name}</h1>
))}
</div>
</div>
);
}
Errors
The error is because the posts array is empty initially you need to check first if the array has some data then perform a map
setPosts(res.data.product)
{posts?.map((post) => (
<h1>{post.name}</h1>
))}
or you can use conditional like this
{ posts.length > 0
? posts.map((post) => (
<h1>{post.name}</h1>
))
: <Your custom message/>
}
res.data is indicated to be an object in the console.log. the map method will only work on arrays. If you were expecting an array, make sure you aren't hitting the "detail" endpoint, which would return specific information about a post.

Firestore data in a flatlist with react native

I've been trying to output data from my Firestore db to a Flatlist in React native but so far unsuccesfull.
I've used this Flatlist for RN and Firestore docs as reference to getting started but for some reason I am missing something here regarding the output method of the Flatlist because it wont output the flatlist itself. When I console log the locations array it shows me all the docs inside that i've queried so it does push them all into an array and my understanding is of FlatLists that they need an array to function but it does not throw any error just doesn't render. Any help more than welcome!
useEffect(async () => {
const locations = [];
const querySnapshot = await getDocs(collection(db, "Location"));
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
locations.push(doc.data());
console.log(locations);
});
return () => querySnapshot();
}, []);
return (
<View style={styles.screen}>
<Text>hello</Text>
<FlatList data={locations}
renderItem={({ item }) => (
<View >
<Text>name: {item.name}</Text>
<Text>Depth: {item.depth}m</Text>
<Text>GeoLocation: {item.geo}</Text>
<Text>id: {item.uid}</Text>
</View>
)}
/>
Your variable locations is defined in your useEffect. The FlatList can not access it. You need to create a state via useState and store the data in there once it is loaded. Setting the state will cause a rerendering of the component and the FlatList will be updated with the new data.
Here is one possible implementation.
const SomeScreen = () => {
const [locations, setLocations] = useState([])
useEffect(() => {
const loadData = async () => {
const querySnapshot = await getDocs(collection(db, "Location"));
setLocations(querySnapshot.map(doc => doc.data()))
}
loadData()
}, [setLocations]);
return (
<FlatList data={locations}
renderItem={({ item }) => (
...
)}
/>
)
}
Here is a simple way:
import React, {useState} from 'react';
import { Button, View, Text, FlatList } from 'react-native';
import {query, where, collection, getDocs } from 'firebase/firestore';
import {db} from './firestoreconfig.js';
const App = () => {
const [cities, setCities] = useState([]);
async function readData()
{
setCities([]);
const mycities = [];
const q = query(collection(db, "cities"), where("capital", "==", true) );
const querySnapshot = await getDocs(q);
querySnapshot.forEach( (city) => {mycities.push({key: city.id, name: city.data().name} )})
setCities(mycities);
}
return (
<View
style = {{marginTop: 50}}
>
<Button
title='Read Data'
onPress={ () => readData()}
/>
<FlatList
data={cities}
renderItem = {
({item}) =>
<Text>{item.key} {item.name}</Text>
}
/>
</View>
);
}
export default App;

How to set local array to global react?

I have an array of Names(Commented in code):=
export default Main_homepage = (props) => {
var Names = []
useEffect(() => {
fetch('https://www.amrutras.com/Items.php')
.then((response) => response.json())
.then((responseJson) => {
{
Names = responseJson //***Names Array***
console.log(Names[0].ID) //****Its working, I am getting outpu for this in console
console.log(Names[0].Name)
}
})
.catch((error) => {
console.error(error)
})
})
return(
<View>{console.log(Names[0].ID)}</View> //****Its not working.
)
}
But when I am trying to access outside of the use effect it's not working.
In short, I am trying to access the response array in JSX.
As suggested by Praveen Kumar sir, utilize useState hook.
Here is the Full Working Example: Expo Snack
import React, { useEffect, useState } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
export default App = (props) => {
const [names, setNames] = useState([]);
useEffect(() => {
fetch('https://www.amrutras.com/Items.php')
.then((response) => response.json())
.then((responseJson) => {
{
console.log(responseJson);
setNames(responseJson); //***Names Array***
}
})
.catch((error) => {
console.error(error);
});
}, []);
return (
<View style={{ marginTop: Constants.statusBarHeight }}>
<Text>{JSON.stringify(names)}</Text>
</View>
);
};
So this is an asynchronous call and it will not work because after the return statement is sent out, the value gets changed.
Change Names into a state hook - Using the State Hook:
// Remove this
// var Names = []
// Replace with:
const [Names, setNames] = useState([]);
And when you're updating, use setNames:
// Remove this inside the promise
// Names = responseJson
// Replace with the following:
setNames(Names);
If you want to understand what an asynchronous call, read more at How do I return the response from an asynchronous call?

How do I set state using useState inside the useEffect method?

I'm making a simple API call from a react component to my Mongo database, which returns a list of items.
Inside useEffect, I'm making a GET request to return an arrays of reviews. When I log the resulting to the data, I'm seeing the correct information:
useEffect(() => {
axios.get('http://localhost:3000/all-reviews')
.then((allReviews) => {
console.log(allReviews)
})
})
However, when I try to set state inside the useEffect method, my program breaks. I know that setState is async, so how do I configure it so it works inside useEffect?
Here's the entire component used to control API calls:
App.jsx
import React, {useState, useEffect} from 'react'
import axios from 'axios'
const App = () => {
const [reviews, setReviews] = useState([])
useEffect(() => {
axios.get('http://localhost:3000/all-reviews')
.then((allReviews) => {
setReviews(allReviews)
})
})
return (
<>
<h1>React development has begun!</h1>
{
reviews.map((item, index) => {
<h1>item.title</h1>
})
}
</>
)
}
export default App
Not that relevant, but here's the route this component invokes:
server.get('/all-reviews', (req,res) => {
Review.find()
.then((result) => {
res.send(result)
})
.catch(err => {
console.log(err)
})
})
I think firstly, your useEffect doesn't have a depedency, which mean it will run every time, it needs an empty array at least, like the one below.
useEffect(() => {
},[])
And when you are expecting a JSON data in React, you have to check if the data is available first before populating it, if not react will freak out.
You could do this.
return (
<>
<h1>React development has begun!</h1>
{
reviews?.map((item, index) => {
<h1>item.title</h1>
})
}
</>
)
}
or this
return (
<>
<h1>React development has begun!</h1>
{
reviews && (reviews.map((item, index) => {
<h1>item.title</h1>
}))
}
</>
)
}
and thirdly you are not returning anything in your dom.
it should be this way.
reviews && (reviews.map((item, index) =>
<h1>item.title</h1>
))
or if you wanna do it your way, you could just do this.
reviews && (reviews.map((item, index) => {
return (
<h1>item.title</h1>
)
}))

Store api response to an array using react useState

I am new to react hooks. I am trying to cast API response into an array using react useState hook. It's giving me empty with the below approach
const [post, setPostArray] = useState([]);
useEffect(() => {
const postparams = { userList: result };
axios
.get(environment._urlPosts, { headers, params: postparams })
.then(posts => {
// storing response data in array
setPostArray(posts.data.post);
console.log(post);
})
.catch(err => {});
}, []);
Then I used the below approach and I was able to see data is printing in the console log
axios.get(environment._urlPosts, { headers, params: postparams }).then(posts => {
// storing response data in array
for (let obj of posts.data.post) {
post.push(obj)
}
setPostArray(post)
console.log(post)
But when I try to iterate this post array in my JSX, it's giving me empty array.
</div>
{/* array length */}
{post.length}
{post.map(post =>
<div className="card">
<Post username={post.username} fullname={post.fullname} postedTime={post.postedTime} postContent='Hi' tweeterLike={post.tweeterLike} />
</div>
)}
Can you please help me to resolve this?
Here is a minimal Example of what you are trying to achieve.
This is the working code:
import React, {useEffect, useState} from "react";
import "./styles.css";
export default function App() {
const [post, setPostArray] = useState([])
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => {
console.log(json);
setPostArray([json]);
})
// setPostArray([{name: 'a'}, {name: 'b'},{name: 'c'}])
},[])
console.log(post)
return (
<div className="App">
{
post.map(item => <div>{item.title} </div>)
}
</div>
);
}
Here is the link to the example in codeSandBox: https://codesandbox.io/s/jovial-snow-773kp

Resources