I'm using here useState to store data, update current value, by using this it's not store previous data, it's only store update current value which do useState. But I want to store previous data and update data all of them, somethings like, i have 10 api's data and i want to call them end of my api using ids.
i want to store 10 api's data in one array.
how to store 10 apis data in together using useState();
my code is somethings like:
const [dataLoc, setDataLoc] = useState([]);
const ids = [1,2,3,4,5,6,7,8,9,10]
useEffect(() => {
ids?.map((id) => {
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then((response) => response.json())
.then((dataLoc) => setDataLoc(dataLoc.title))
.catch((error) => console.error(error))
})
}, []);
console.log(dataLoc);
output is:
but it's in 10 array the out put but i want all the title in one array.
anyone can help me how can i do this here? ThankYou for Your Trying in advance!
CodePudding user response:
You can make use of react states prev
-callback like that:
const [dataLoc, setDataLoc] = useState([]);
useEffect(() => {
ids?.map((id) => {
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then((response) => response.json())
.then((dataLoc) => setDataLoc((prev) => [...prev, dataLoc.title]))
.catch((error) => console.error(error));
});
}, []);
console.log(dataLoc);
By spreading ...prev
and appending it with , dataLoc.title
you add each entry to the previous state value. The order is the one in which the calls go through, since we insert the new element at the end.
Edit
If you want to console.log multiple times you can make use of another useEffect
inside your component:
useEffect(() => {
console.log(dataLoc);
}, [dataLoc]);
CodePudding user response:
Issue
The code is enqueueing state updates in a loop and not updating from the previous state. In other words, each enqueued update in the loop overwrites the previous update. The update from the last loop iteration is the one the app sees on the subsequent render.
Solution
Either use a functional state update to correctly enqueue state updates and update from the previous state. Use .forEach
instead of .map
.
const [dataLoc, setDataLoc] = useState([]);
useEffect(() => {
ids?.forEach((id) => {
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then((response) => response.json())
.then((dataLoc) => setDataLoc(dataLoc => [...dataLoc, dataLoc.title]))
.catch((error) => console.error(error))
})
}, []);
Or map the ids
to an array of Promises and Promise.all
them and enqueue a single state update.
const [dataLoc, setDataLoc] = useState([]);
useEffect(() => {
const requests = ids?.map((id) => {
return fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then((response) => response.json())
.then((dataLoc) => return dataLoc.title)
.catch((error) => console.error(error))
});
Promise.all(requests)
.then(ids => {
setDataLoc(ids)
});
}, []);
CodePudding user response:
In your case it is overriding the previous values. You can merge the values
React.useEffect(() => {
ids?.map((id) => {
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then((response) => response.json())
.then((dataLoc) =>
setDataLoc((prevState) => {
return [...prevState, dataLoc.title];
})
)
.catch((error) => console.error(error));
});
}, []);
CodePudding user response:
you can use push method to add each title to the Array:
const [dataLoc, setDataLoc] = useState([]);
const ids = [1,2,3,4,5,6,7,8,9,10]
useEffect(() => {
ids?.map((id) => {
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then((response) => response.json())
.then((dataLoc) => setDataLoc(dataLoc.push(dataLoc.title)))
.catch((error) => console.error(error))
})
}, []);
console.log(dataLoc);