1

i had read some questions and article about this issue including this one: but i don't find my answer.

consider this code.

function Component({ page }) {
  
  const [list, setList] = useState([]);
  
  useEffect(() => {
    
    axios.get([url] + page).then(newList => {
      setList([...list, ...newList]);
    });
    
  }, [page, list]);
  
  return ['some jsx for map though list'];
};

i have a pagination and every time i go to next page i need to concatenate the data with previous one, here is the deal.

  • the react complains about dependency array about list and page.

  • i'm agree about page because each time it changes i need to fetch more data. but when i add list to dependency array useEffect find changes in list and fetch more data which cause infinit loop.

i know about hooks but i wonder what is the best practise to solve this issue.

Amir Rezvani
  • 1,262
  • 11
  • 34

1 Answers1

2

Your list updates on each page or list dependency update, resulting in an infinite loop. Removing the list argument from the dependency array will fix your bug.

In fact, if you use callback in setState like blew eslint never complain about the list in the dependency array. so you can safely remove the list from useEffect dependency array.

Inside the useEffect, you'd not need list at all.

useEffect(() => {
    
    axios.get([url] + page).then(newList => {
      setList(prev => [...prev, ...newList]);
    });
    
  }, [page]);

Since the method is defined in this component, you'd not even need useCallback hooks to memoize the funtion. And eslint won't throw warnings too

MORÈ
  • 2,480
  • 3
  • 16
  • 23
kanuos
  • 985
  • 9
  • 16
  • this is a sample code but react complain about the list and told me you have to add the list in the dependency array. – Amir Rezvani Jun 28 '22 at 13:44
  • Are you using react18? In that case, I might have to look up the latest documentation for `useEffect`. Another workaround might be to use `useMemo` for your list and remove `useState` and `useEffect` completely – kanuos Jun 28 '22 at 13:47
  • if `eslint` give you prob then paste this `// eslint-disable-next-line react-hooks/exhaustive-deps` end of useEffect hook. like this one `useEffect(() => { if (_createChannelSuccess) { closeDialog(); dispatch(createChannelSuccess(false)) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [])` – Mohit Sharma Jun 28 '22 at 13:50
  • the react version is 17.0.2 @kanuos – Amir Rezvani Jun 28 '22 at 13:51
  • @AmirRezvani in that case there shouldn't be any problem, try removing all `list` variable usage inside the `useEffect` and add `setList` to the dependency array – kanuos Jun 28 '22 at 13:55
  • 1
    sorry @kanuos i did not see you used callback inside of setState so i accept your answer. – Amir Rezvani Jun 29 '22 at 19:40
  • @AmirRezvani I'm glad it solved your issue. BTW, it's not because I used a `callback` inside `setList` that `eslint` didn't scream. In your initial question you were using the `list` variable directly inside the `useEffect`. Since you were using it and not adding it in dependency array, esLint was complaining. However, on adding it in dependency array it rendered an infinite loop. I used a callback as that always gets the previous value of the state. – kanuos Jun 30 '22 at 13:21
  • 1
    @kanuos exactly. i was aware of adding list cause infinite loop because of directly use inside of useEffect what is i am not aware of was if we use callback in setState we use the list indirectly and eslint never complaining about it. thanks to you i know now. – Amir Rezvani Jul 01 '22 at 10:23