Reputation: 71
I have an array with ids like [123,345,212,232.....] I have a Rest API that responds the particular product with respect to an id .
So in ReactJS, how would I loop through the array and get the products and store in state
I tried doing this in useEffect{running once as in componentDidMount} but it only stores the first product in array.
Are there better ways to accomplish this?
My Actual Code that has the problem is
useEffect(() => {
const getBought = async () => {
user.bought.map(async (boughtID) => {
let bought = await get(`/bought/${boughtID}`, {}, true);
let boughtDate = bought.createdAt.slice(0, 10);
bought.products.map(async (pr) => {
let product = await get(`product/${pr.product}`);
let quantityBought = pr.quantity;
setAllBoughts({
...allBoughts,
[boughtDate]: [
...(allBoughts.boughtDate || []),
{
product,
quantityBought,
},
],
});
});
});
};
getBought();
}, []);
So I have a user which has arrays of boughtIds in bought key...
so I am looping throughout those bought keys
A bought schema has products which has product id and number of product bought (pr.product and pr.quantity).. So I am hitting the API , and save all the products in a state object.
so allBoughts is state which is an object that has keys as (dates) as in the code .createdAt.slice(0,10) which gives me date removing rest of stuffs mongodb added.
But everytime I do it, there are few things that happen.
Either only the first item is saved, and rest are not Either the same item gets overwritten or the page reloads infinitely(especially whrn I try to remove dependency array from useEffect)
Upvotes: 0
Views: 445
Reputation: 84912
setAllBoughts({
...allBoughts,
[boughtDate]: [
...(allBoughts.boughtDate || []),
{
product,
quantityBought,
},
],
});
allBoughts
is the state that existed when this effect ran. Ie, it's the empty state, with no results in it yet. So every time a result comes back, you are copying the empty state, and adding one entry to it. This erases any results you have.
Instead, you need to use the most recent version of the state, which you can do with the function version of set state:
setAllBoughts(prevState => {
return {
...prevState,
[boughtDate]: [
...(prevState.boughtDate || []),
{
product,
quantityBought,
},
],
};
})
Upvotes: 2
Reputation: 4561
From what you're saying, it seems to me that you're erasing the previous stored result in the state (You get result for id 123, store it, then result of 345, store it and erase the previous value). Or you're just not looping through the array.
Here is an example of how to GET multiple times in a useEffect
and assign all the results in the state.
Fully working example at Codesandbox
export default function App() {
const ids = useRef([1, 3, 5]);
const [items, setItems] = useState([]);
useEffect(() => {
const promises = ids.current.map((id) => fetchData(id));
Promise.all(promises).then((responses) => {
setItems(responses);
});
}, []);
async function fetchData(id) {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
return response.json();
}
return (
<div className="App">
{items.map((item) => (
<div key={item.id}>
{item.id} - {item.title}
</div>
))}
</div>
);
}
Upvotes: 0