skip to Main Content

Lets say I have

const [variable, setVariable] = useState(false)

I am trying to do

useEffect(() => {
  if (variable==false){
    setTimeout(() => {
       if (variable==false) {do_something();}
       else {do_something_else();}
    }, n)
  }
}, [variable]);

But the issue is since the inner variable==false isn’t giving correct results as setVariable is asynchronous.

Initially variable is false. some event is fired which is supposed to set it to true via setVariable(true) at around 2 sec. So for n<2 sec I am expecting to be false and n > 2 sec I am expecting it to be true. right ? Now no matter whatever I set n it never goes into do_something(). when I an trying to do this way even if I set n = 1 or 0.5 second I am finding it has already become true from false.

2

Answers


  1. useEffect(() => {
      if (variable) {
        setTimeout(() => {
          do_something_else();
        }, n);
      } else {
        setTimeout(() => {
          do_something();
        }, n);
      }
    }, [variable]);
    
    Login or Signup to reply.
  2. The value of variable inside the setTimeout callback will be the value that variable had when the setTimeout was set, not the value that variable has when the setTimeout callback is executed. This is because JavaScript closures capture the environment in which they are created, which includes the variable value at the time the setTimeout is called.

    One way to get the current value of the state inside the setTimeout callback is to use a ref to track the latest value. Here is how you can do this:

    import { useState, useEffect, useRef } from 'react';
    
    const YourComponent = () => {
      const [variable, setVariable] = useState(false);
      const variableRef = useRef(variable);
    
      useEffect(() => {
        variableRef.current = variable;
      }, [variable]);
    
      useEffect(() => {
        if (variable == false) {
          setTimeout(() => {
            if (variableRef.current == false) { 
              do_something(); 
            } else { 
              do_something_else(); 
            }
          }, n);
        }
      }, [variable]);
    }
    

    In this code, variableRef.current will always hold the latest value of variable. When you update the state by calling setVariable, the variableRef.current value will be updated in the subsequent useEffect call. Then, inside the setTimeout callback, you can check variableRef.current to get the latest value.

    This way, even if setVariable is asynchronous, your setTimeout callback will always have access to the latest state value when it is executed.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search