React: unable to fetch state inside setInterval

I have a button on which I need to call a setInterval but if the interval is already set then I don’t want to initiate another setInterval.

So this is how I have implemented it ():

export default function App() {
  const [intervalId, setIntervalId] = useState(null);

  const startInterval = () => {
    console.log("inside startInterval", intervalId);
    if (!intervalId) {
      console.log("starting Interval", intervalId);
      const _intervalId = setInterval(() => {
        console.log("Interval Id inside setInterval is", intervalId);
      }, 2 * 1000);
      setIntervalId(_intervalId);
    } else {
      console.log("Rejecting set interval");
    }
  };

  const onBtnClick = () => {
    console.log("btn clicked");
    // make API call
    startInterval();
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={onBtnClick}>Click Me</button>
    </div>
  );
}

but inside setInterval I always get to see the default value of state i.e. null in my case.
How can I access the latest value inside setInterval?

Click here to go to Live Code Sandbox

3 thoughts on “React: unable to fetch state inside setInterval”

  1. Your code is working. While the log shows the intervalId as null, that’s only because the function that the interval closes over was initialized when the intervalId was indeed null.

    A variable declared with const can’t be reassigned; the intervalId starts out as null during the render when the button is clicked, and the startInterval function closes over that null. When startInterval is called, and the anonymous callback is declared:

    () => {
      console.log("Interval Id inside setInterval is", intervalId);
    }
    

    it still closes over the null intervalId.

    If you wanted to see the interval ID inside the callback, use a ref instead.

    const intervalIdRef = useRef();
    // ...
    intervalIdRef.current = setInterval(() => {
      console.log("Interval Id inside setInterval is", intervalIdRef.current);
    }, 2 * 1000);
    
    Reply

Leave a Comment