Home > Back-end >  react-hooks/exhaustive-deps on a function passed via props
react-hooks/exhaustive-deps on a function passed via props

Time:10-11

I'm getting the react-hooks/exhaustive-deps warning on an element that calls a function passed via props(onCountdownEnd) in the useEffect hook, that is used to direct the application flow on the countdown end:

function Countdown(props: { seconds: number; onCountdownEnd: () => void }) {
  const [count, setCount] = useState(props.seconds);

  useEffect(() => {
    if (!count) props.onCountdownEnd();
    const intervalId = setInterval(() => {
      setCount(count - 1);
    }, 1000);

    return () => clearInterval(intervalId);
  }, [count]);

  return <span className="text-xxl">00:0{count}</span>;
}

React Hook useEffect has a missing dependency: 'props'.

What is the correct way to approach this warning? I'm not sure I want to include props in the dependancies array here. Thanks!

CodePudding user response:

Don't include the props object, since it changes on each render. You should destructure the props, and include the exact dependency:

function Countdown({ seconds, onCountdownEnd }: { seconds: number; onCountdownEnd: () => void }) {
  const [count, setCount] = useState(seconds);

  useEffect(() => {
    if (!count) onCountdownEnd();
    const intervalId = setInterval(() => {
      setCount(count - 1);
    }, 1000);

    return () => clearInterval(intervalId);
  }, [count, onCountdownEnd]);

  return <span className="text-xxl">00:0{count}</span>;
}

However, in your code the interval would be cleared and added on each change of count. You can refactor it to use the useState updater function to avoid it, and handle onCountdownEnd in another useEffect block:

function Countdown({ seconds, onCountdownEnd }: { seconds: number; onCountdownEnd: () => void }) {
  const [count, setCount] = useState(seconds);

  useEffect(() => {
    const intervalId = setInterval(() => {
      setCount(current => current - 1);
    }, 1000);

    return () => clearInterval(intervalId);
  }, []); // no dependencies
  
  useEffect(() => {
    if (!count) onCountdownEnd();
  }, [count, onCountdownEnd]);

  return <span className="text-xxl">00:0{count}</span>;
}

CodePudding user response:

when you use a function or a variable in useEffect you have to pass them as dependencies array because the functionality of the callback is based on their value . sometimes you dont need to re-run useEffect when they are changed so you can ignore the warning but in your case you can do this: place this line of code before useEffect

const onCountdownEnd = {props}

and in your useEffect

if (!count) onCountdownEnd();

and finally pass onCountdownEnd to the dependency array

  • Related