react-js-lazy-setstate-issues
React JS - Lazy setState Issues

React JS - Lazy setState Issues

Written : 2021-02-12 Last Update : 2021-02-12

Initial Project Setup

We will use the same things that we do while setting up a project. Let's not make this blog any longer than it need to be. I just switched to 60% keyboard and I am not used to it.😭

npx create-react-app state_issue

Normal State

We have an App.js file with a button and a simple <h1> which simply shows the current counter value. yes, I get it, it's a simple counter app, but wait it is going to be more than enough to show this issue.

import { useState } from 'react';
 
function App() {
  const [counter, setCounter] = useState(0);
 
  function increase() {
    setCounter(counter + 1);
  }
 
  return (
    <div>
      <h1>Counter : {counter}</h1>
      <button onClick={increase}>Increase</button>
    </div>
  );
}
 
export default App;

Run this and click on the counter button 5 times and the counter value will be 5, just as we expect it to be.

The Issue

Now to create an issue, let's add an lazyIncrease function that calls setCounter but with a setTimeout which will update the counter only after 2 seconds.

// add this function
  function lazyIncrease() {
    setTimeout(() => {
      setCounter(counter + 1);
    }, 2000);
  }
 
// add this button after the increase button
<button style={{ marginLeft: '12px' }} onClick={lazyIncrease}>Lazy Increase</button>

Not refresh the page so that the counter resets to 0. Then first click the Lazy increase button once and then the increase button 5 times. The counter will go to 5 and will then automatically be set to 1.

This arises because when we clicked the Lazy increase button the value was 0 and javascript will use that to increase counter after 2 seconds, hence setting it back to 1.

The Solution

We will call the callback method to update state , which will then use the current value to update it.

Replace the lazyIncrease function with this and then repeate the same click process. First click the Lazy increase button once and then the increase button 5 times. The counter will go to 5 and will then automatically be set to 1.

  function lazyIncrease() {
    setTimeout(() => {
      setCounter((counter) => counter + 1);
    }, 2000);
  }

Now , you will see that the count is actually 6, what it is supposed to be.

So if you ever have to use any lazy update on any state value, then use the callback method to update it and such bugs will not arise.

If you found this helpful , follow me on other social media for Updates.