Home > Mobile >  how useState really work when state change and state not change
how useState really work when state change and state not change

Time:12-13

I test some code and make me confused

There are two reproduction,

  1. use setState function set State to same previous state value
const [state, setState] = useState(1)
setState(() => 1)
  1. use setState function set State to same value(always same ex: 1, true, something else), but different initial state
const [state, setState] = useState(1)
setState(() => 2)

This is reproduction sample 1

always set state to same value

open codesandbox console first and clear it first.

what happened

click, state is already 1, setState function set state to 1,

component function does not re-run

// console show 
test 
test
test

This is reproduction sample 2

set state to certain value

I always set state to 2.

First click, state is change from 1 to 2, so component function re-run

// console
test
app

Second click, state already is 2, but why component function still re-run

// console 
test 
app   <--------------  here component function re-run

Third click, state already is 2 , component function does not re-run

// console 
test 

The Problem is Here

In Sample 2, second click button, state is same as previous, but is still re-run component.

And we go back to see Sample 1 and third click in Sample 2, these two state change step is same as Sample 2 second click, they are all same set same state compare to previous state, but how they output is different

As I know, state change will cause component function re-run.

What I expect is Sample 2 second click, component function is not re-run

CodePudding user response:

Let's focus only on Simple 2 as Simple 1 flow is what a developer would expect.

Simple 2 logs are as follow:

1. app  // first render
2. test // button click, log from the callback 
3. app  // state change from '1' to '2', second render
4. test // second button click
5. app  // no state change, why the log?
6. test // 3rd button click
7. test // 4th button click etc.

So the main question is why there is a 5th log of 'app'. The reasoning behind it hides somewhere in React docs under Bailing out of a state update:

Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React won’t unnecessarily go “deeper” into the tree.

In simple words, its just an edge case where React needs another render cycle but it doesn't goes into the Nodes tree (i.e it doesn't run the return statement, in your example it's a React.Fragment <></>)

A more concrete example, notice the addition log of "A":

const App = () => {
  const [state, setState] = React.useState(0);

  useEffect(() => {
    console.log("B");
  });

  console.log("A");

  return (
    <>
      <h1>{state}</h1>
      <button onClick={() => setState(42)}>Click</button>
    </>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
  • Related