Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

State is not updated in StrictMode

Tags:

After some trial I discovered following problem occurs in strict mode. I would be interested if someone can explain why.

Take this simple example where inside render I am just scheduling a timeout which updates state:

Example:

let firstRender = true; // Normally I would use ref but I was playing with example

export default function App() {
  let [data, setData] = React.useState({ name: 'Nick' });

  // Schedule a timeout on first render
  if (firstRender) {
    setTimeout(() => {
      console.log('Running');

      setData((ps) => ({
        ...ps,
        name: 'Paul',
      }));
    }, 1000);
  }

  console.log('Running render');
  firstRender = false;

  return (
    <div>
      <h1>{data.name}</h1>
      <p>Start editing to see some magic happen :)</p>
    </div>
  );
}

If you run this example without Strict mode, then you will see "Paul" on screen after one second, as I was expecting.

If you use Strict mode, it will always show "Nick" on screen. Idea why?

Note: it seems using useRef instead of the global variable firstRender fixes this problem also in Strict mode. This seems to happen because ref was set in first render, and its value also got discarded (see also the answer).

like image 395
Giorgi Moniava Avatar asked Sep 30 '21 13:09

Giorgi Moniava


People also ask

Why is React not updating on state change?

State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.

How do I update state in render?

Whenever we update the state using the setState() method it re-renders the current component and its child components. When we call the setState function it receives the latest state snapshot. Then we can use it inside the setState() function and return the new value to which we want to update the new state value to.

How do I update my state data in React?

To update our state, we use this. setState() and pass in an object. This object will get merged with the current state.

What does React StrictMode mean?

StrictMode is a tool for highlighting potential problems in an application. Like Fragment , StrictMode does not render any visible UI. It activates additional checks and warnings for its descendants. Note: Strict mode checks are run in development mode only; they do not impact the production build.


1 Answers

This is due to the fact that strict mode intentionally invokes your function component body twice (when in dev mode) to help spot unintended side effects.

On the second invocation, your firstRender variable is false so your setTimeout doesn't run.

Important to note that this second invocation isn't just a re-render like you'd get from a state update. It's a second invocation of the entire component body. State is not preserved. React invokes your component function once, discards the result, and invokes it a second time to get the output.

From the docs:

Because the above methods might be called more than once, it’s important that they do not contain side-effects.

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:

  • Function component bodies
like image 50
ray hatfield Avatar answered Sep 21 '22 05:09

ray hatfield