Person
Person

Reputation: 2269

Is there a way to avoid infinite loop of dependencies and to pass the correct dependencies to useEffect hook in this case?

I have a custom hook which gets a callback as one of the arguments and calls it in useEffect

const customHook = (callback: Function) => {
  ...
  useEffect(() => {
    if (something) {
      callback();
    }
  }, [other things, callback]);

  return {values}
}

The problem here is that callback is a function and causes useEffect to run in a loop. EsLint suggested useCallback in a parent component. So I decided to wrap this callback in a useCallback where I am calling my customHook.

So I would have something like this in my component:

const memoizedCallback = useCallback(() => {
    myFunction(values);
  }, [values, myFunction]);

  const { values } = customHook(memoizedCallback);

And here I have my problem - dependencies of myFunction are returned from customHook and I can not use them before they defined. But I also can not put memoizedCallback after customHook call because of the same reasons.

And now I am stuck in this infinite loop of dependencies and I am not sure how to solve this, if somehow, without just ignoring eslint warning.

So any ideas and solutions will be much appreciated :)

Upvotes: 0

Views: 76

Answers (1)

Ori Drori
Ori Drori

Reputation: 191976

If changing the callback shouldn't cause the useEffect block to be executed set the callback to a ref:

const customHook = (callback: Function) => {
  const fn = useRef(callback);
  
  ...
  
  useEffect(() => {
    fn.current = callback;
  })
  
  useEffect(() => {
    if (something) {
      fn.current(); // fn.current?.() if fn.current might be undefined
    }
  }, [something]);

  return {values}
}

Upvotes: 1

Related Questions