Home > Enterprise >  where to clear setTimeout in react?
where to clear setTimeout in react?

Time:10-01

  useEffect(() => {
    const id_1 = setTimeout(() => {
      // do something
      clearTimeout(id_1);
    }, 500);
  }, [success_failure_msg[0]]);

vs

  useEffect(() => {
    const id_1 = setTimeout(() => {
      // do something
    }, 500);
    return () => clearTimeout(id_1);
  }, [success_failure_msg[0]]);

What is the difference and which is the correct practice?

CodePudding user response:

The correct practice is the second one that you provided. To answer your question you really have to understand why we clear the timeout.

Let's take an example of a simple react component:

const Comp = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount(1); // set the count in the timeout
    }, 1000);
  }, [setCount]);

  return (
    <div>count: {count}</div>
  );
}

Now this will work as long as the component is rendered. But what happens if the component gets unmounted before the timeout is resolved. The timeout will still run and you will be calling setCount of a component that is no longer in the view.

If you change it to the code you have given in your first example the problem is still the same:

  useEffect(() => {
    const id_1 = setTimeout(() => {
      clearTimeout(id1); // this does not do anything as the timeout has already run
      setCount(1); // set the count in the timeout
    }, 1000);
  }, [setCount]);

The clearing the timeout does not do anything and you will still have a memory leak. The only way to resolve it is to return a function from the useEffect that react will run when it unmounts the component. Within that function you can clean up the code.

  useEffect(() => {
    const id_1 = setTimeout(() => {
      setCount(1); // set the count in the timeout
    }, 1000);
    
    // React will run this function when it unmounts and so no memory leak
    return () => clearTimeout(id_1)
  }, [setCount]);

CodePudding user response:

both seems wrong to me, cleartimeout should be before settimetimeout and when success_failure_msg changes two time the settimeout trigger only once.

Example

var id_1 = undefined;
useEffect(() => {
    clearTimeout(id_1)
    id_1 = setTimeout(() => {
       success_failure_msg // shoule be test2
    }, 500);
  }, [success_failure_msg]);
  
  success_failure_msg = "test";
  success_failure_msg = "test2"

  • Related