I have been learning react recently, and I created a component in which I have created three buttons: "post", "user", and "comment". When I click one of the buttons, the name of the button shows below the buttons and also logs the button's name, which is console. I am confused as to why a button logs the name only twice in console if clicked consecutively, since from my understanding it should log only once. I tried removing <React.StrictMode> from the index.js file but still it only logs twice. Example: if the user button is clicked twice consecutively, it logs its name twice but not more if clicked again, it should log into the console only once. I think it is related to the useState hook. Please help me understand this react behaviour. Here is my code:
export default function Hello() {
const [resourceType, setResourceType] = useState('post')
console.log(resourceType)
return (
<div>
<button onClick={() => setResourceType('post')}>Post</button>
<button onClick={() => setResourceType('user')}>User</button>
<button onClick={() => setResourceType('comment')}>Comments</button>
<h1>{resourceType}</h1>
</div>
)
}
CodePudding user response:
As @Armands Uiska alluded to in his comment, the answer is in the React docs (API Hooks Reference) buried in this post which states:
Bailing out of a state update
If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects.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. If you’re doing expensive calculations while rendering, you can optimize them with useMemo.
So if your case, since the console.log(...)
is in the component body, it's still being fired before React "bails out".
CodePudding user response:
React components automatically re-render whenever there is a change in their state or props. in your case clicking the button the first time, changes the state setResourceType('post')
which causes a re-render
and executes console.log(resourceType)
. but clicking it the second time will not change the state it is the same resourceType = 'post'
in this phase React may still need to re-render that specific component again and console.log(resourceType)
will be executed. then it stops rerendering in spite of clicking the button .
Note : onClick
is an Event handler only re-run when you perform the same interaction again (clicking the button )
change your component like this if you want to log resourceType
to the console every time you click the button :
const [resourceType, setResourceType] = useState('post')
return (
<div>
<button onClick={ ()=>{ setResourceType('post'); console.log( resourceType)} }>Post</button>
<button onClick={() =>{ setResourceType('user'); console.log( resourceType)}}>User</button>
<button onClick={() => {setResourceType('comment'); console.log( resourceType)}}>Comments</button>
<h1>{resourceType}</h1>
</div>
)
CodePudding user response:
The reason can be found in the react documentation React docs (API Hooks Reference)
Bailing out of a state update If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects.
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. If you’re doing expensive calculations while rendering, you can optimize them with useMemo.