0

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)

2
  • 1
    I tried doing this in useEffect{running once as in componentDidMount} but it only stores the first product in array. This sounds like the right approach, it just had a bug in it. Please show us the code you wrote for this Commented Mar 19, 2021 at 3:17
  • Can you see my code, I have edited the post Commented Mar 19, 2021 at 11:23

2 Answers 2

2
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,
      },
    ],
  };
})
Sign up to request clarification or add additional context in comments.

1 Comment

ohh, thanks.. I knew this in class components, but didnt know this could be done in hooks as well
0

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>
  );
}

1 Comment

Can you see my code, I have edited the post

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.