0

I was creating a custom hook in React when I encountered behaviour of useEffect hook that I was not expecting. I created a custom hook that takes an array of IDs and fetches data for every ID and whenever the IDs change, it fetches again and then returns all of the data in one array:

const useGetItems = (ids) => {
  const [data, setData] = useState([]);

  useEffect(() => {
    const loadData = async () => {
      const responses = ids.map((id) => fetchById(id));
      const parsed = await Promise.all(responses);
      setData(parsed);
    };
    loadData();
  }, [ids]);

  return data;
};

However, when I tested it with an array of IDs defined like const ids = [1,2] and passed them into useGetItems, the useEffect hook started to loop endlessly. After some debugging, I found that when I put ids into state using useState, the issue is gone. Also commenting out the setData caused the endless loop to stop.

You can find the full example here. You can uncomment problematic lines and see a log of every call of fetchById in the console.

Why does it behave like this? Is it because the data outside React state are not equal when compared by React even if they don't change?

1 Answer 1

1

For some reason couldn’t post this as comment, anyway. I think that’s caused by Referential equality, if the IDs in the main component is declared as variable, then a new reference will be created on each render,can you provide the code of the parent component(that’s using the hook)?

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, the code is on this link, you have to comment out L28 and uncomment L29 to see it behaving in a way I described.
As i said up, the issue is that id variable is creating a new instance of this array on each render and then will cause loop of setting state over and over again which results in endless loop , hope that was clear
Yes, that's clear, thanks. However, I still don't know why is it triggered only when the state in the hook is updated. When you remove the L18 setData(parsed) , the useEffect hook doesn't end in an infinite loop. Or is it because when the state of the hook is not updated, the new render of parent component is not called thus the array doesn't change?
you can think of the custom hook as all the code inside of it are written inside the component as far as i know, so that means when you setState in the customhook function that will trigger a rerender on the main component.

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.