1

I have a code in which state should be incremented by 1 every 2 seconds. setState is called inside setInterval callback, but instead of using a typical form of setState: setState(newState) I used a callback form setState(() => {...}) and weird things started happening. Instead of incrementing by 1, the state is being incremented by 2.

Here's the simplification of the offending code:

const handler = () => {
   let val = 0;
   setInterval(() => {
      setState(() => {
        console.log("before inc", { val });
        val = val + 1;
        console.log("after inc\n--------", { val });
        return val;
      });
    }, 2000);
}

The expected logs would be:

before inc {val: 0}
after inc {val: 1}
-------- 
before inc {val: 1}
after inc {val: 2}
-------- 

but instead I've got:

before inc{val: 0}
after inc {val: 1}
-------- 
before inc {val: 2}
after inc {val: 3}
-------- 

which is super weird. What is happening?

Playground: codesandbox

marzelin
  • 10,790
  • 2
  • 30
  • 49

1 Answers1

2

this happens because your App is wrapped with <React.StrictMode>. Strict Mode renders twice your component in development to find any issues, which may cause some side effects like that.

If you remove the wrapping <React.StrictMode> tag your component will render once and your code will work as expected.

buzatto
  • 9,704
  • 5
  • 24
  • 33
  • in strict mode React calls a function passed to `setState` twice, hence the incrementation is doubled but why I don't see console.logs from these additional calls? – marzelin Jan 13 '21 at 17:26
  • 2
    okay, I found the answer in the docs: "Starting with React 17, React automatically modifies the console methods like console.log() to silence the logs in the second call to lifecycle functions.". That's weird. – marzelin Jan 13 '21 at 17:42