Home > Blockchain >  Spreading in a `useEffect` casuing huge number of rerenders
Spreading in a `useEffect` casuing huge number of rerenders

Time:12-04

I have a sort handler defined like so:

  const onSortHandler = useCallback((property: string, direction: string) => {
    setTodoList([...todoList.sort(/**<sort function snipped>**/)]);
  }, [todoList]);

This function is passed down to a child component where I have something like:

  const [sort, setSort] = useState<{ name: string | undefined, direction: string | undefined }>({ name: 'id', direction: 'asc' })

  useEffect(() => {
    onSortHandler(sort.name, sort.direction);
  }, [sort, onSortHandler]);

The idea being that whenever someone changes the sort property and direction, I trigged a new sort and spreading the new object into setTodoList causes a rerender.

Now this works fine, but eslint told me that I should add onSortHandler to the useEffect dependencies array, which I did, and it caused a massive amount of renders, so I followed it's advice and added useCallback into the mix.

So I get a huge amount of renders, making the sort functionality not work. If I remove onSortHandler from the useEffect dependency array, it works fine but I'm getting the eslint warning I'd like to sort.

I know that it's the spread causing the issue as if I remove it, the issue goes away (but then the list never rerenders on a new sort which is another problem).

CodePudding user response:

Make onSortHandler stable (meaning it never changes) like:

const onSortHandler = useCallback((property: string, direction: string) => {
  // use functional state update:
  setTodoList(current => current.slice().sort(/**<sort function snipped>**/));

}, []); // < no dependencies

This allows you to use it as a dependency wherever necessary without it actually triggering any update effects.

Note: I changed the spread to slice (make a copy first), because using .sort on current (or todoList in your code) is still a state manipulation, as sort sorts in place.


Ref: Functional updates

  • Related