import React, { useState } from "react";
export const App = () => {
const [state, setState] = useState(0);
console.log("Render App Render", stateA);
return (
<div className="App">
<button onClick={() => setState(1)}>setState in App Component</button>
</div>
);
};
- On mounting => 'Render App Render 0'
- 1st click on button => 'RenderApp Render 1'
- 2nd click on button => 'Render App Render 1'
- 3rd or more clicks: no log!
Can some explain the reason for me, please?
CodePudding user response:
The best explanation I could find is on the following comment from a Facebook developer. The issue I linked explains the same problem and the reason for the render to happen twice is that:
This is a known quirk due to the implementation details of concurrency in React. We don't cheaply know which of two versions is currently committed. When this ambiguity happens we have to over render once and after that we know that both versions are the same and it doesn't matter.
CodePudding user response:
This is because on the 3rd click, state still equals 1.
Here is the current flow:
on mount: state = 0
1st click: state = 0 or 1
- (depends if state variable is used in the return statement, since remember, setState is asynchronous, and react does not know if the value here has changed yet, from the first click, or not)
2nd click: state = 1
3rd click: state = 1
This logic is partly why React can make massive performance gains compared to other libraries like jquery. React is smart enough to know when to re-render and when not to.
If the state value doesn't change, and React knows this (i.e on 2nd click), React won't re-render/re-calculate what's inside the component.
If state isn't immediately used in the return/rendering logic, React will also choose when to update the component, and that is not always immediately
If you want state to change again on the 3rd click, you can write a function that toggles between two different values, on every click, and attach that to the onClick
button handler.
Usually this function changes a boolean value like so:
() => setState((state) => !state)
Where state is true, then changes to false. On the next click, it changes from false to true, and so forth.
CodePudding user response:
Because after the second click, the state will again be set to 1 by the setState (1) hook. Those. it will be immutable and there is no need for a re-renderer. If you want to rerender after every click you should probably try
<button onClick={() => setState(state )}>setState in App Component</button>
Or another state change
if you are wondering why it is still being re-rendered twice, then this is a well-known bug that has already been documented, and I hope it will be closed soon.