I have an API that returns me 4 objects and I try to save them in a new array called "products" and map them to the DOM. My problem is that map function doesn't work on first render.
If I modify something in my code, save the file and watch the react page again, I will see that my data appeared.
How can I fix that?
import { useEffect, useState } from 'react';
import './App.css';
function App() {
const [products, setProducts] = useState([]);
useEffect(() => {
fetch("URL")
.then(res => res.json())
.then(data => {
for(let i = 0; i < data.length; i++) {
products.push(data[i])
}
})
})
console.log(products);
return (
<div className="App">
{products.map((product,index) => (
<div key={index}>{product.price}</div>
))}
</div>
);
}
export default App;
const [products, setProducts] = useState([]);
useEffect(() => {
async function getdata() {
const res = await fetch("URL");
const data = await res.json();
setProducts(data)
}
let unmounted = false;
if (!unmounted) {
getdata();
}
return () => unmounted = true;
}, []);
You can try this, I hope It will be work.
You're directly mutating state which is a React no-no.
You need to use the setProducts
state setter instead
useEffect(() => {
fetch("URL")
.then(async res => {
if (!res.ok) { // don't forget to check for errors
throw new Error(`${res.status}: ${await res.text()}`);
}
return res.json();
})
.then(setProducts) // pass the resolved data to the state setter
.catch(console.error);
}, []); // use an empty dependency array to only run once on mount
Here's a demo using the JSONPlaceholder /albums
API
First of all, you are missing dependency array in your useEffect
hook. Assuming you want the useEffect
hook to run on initial render, I am passing empty dependency array ( []
).
Next fix is you wait for your data to be set in products, and if products are set (that is you have a products.length > 0
), you call
useEffect(() => {
fetch("URL")
.then(res => res.json())
.then(data => setProducts(data))
}, [])
console.log(products);
return (
<div className="App">
{products.length && products.map((product,index) => (
<div key={index}>{product.price}</div>
))}
</div>
);
you have to run useEffect() only once then u need to call setProducts
useEffect(() => {
fetch("URL")
.then(res => res.json())
.then(data => {
setProducts(data);
})
},[])
The data is fetched after the first render. You might want to use
{Boolean(products.length) && products.map((product,index) => (
<div key={index}>{product.price}</div>
))}
and
useEffect(() => {
fetch("URL")
.then(res => res.json())
.then(data => {
for(let i = 0; i < data.length; i++) {
products.push(data[i])
}
setProducts(products);
})
})
instead
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.