Reputation: 323
import { useState } from "react";
export default function App() {
console.log("rendered...")
const [count, setCount] = useState(0);
const increaseCount = () => {
setCount(count + 1);
};
const setFourValue = () => {
setCount(4);
};
return (
<div className="App">
<div
style={{ display: "flex", alignItems: "center", columnGap: ".25rem" }}
>
<button onClick={increaseCount}>Increase</button>
<button onClick={setFourValue}>Set 4</button>
<span>{count}</span>
</div>
</div>
);
}
I try to figure out when and how component render. Situation that i try to is i increased count to 4 and now my count value is 4. But i click to 'Set 4' button my count value is still 4 but still component re-rendered. After that if click again 'Set 4' button component doesn't re-render. Why ?
Upvotes: 1
Views: 77
Reputation: 1861
There's a problem with your increaseCount
function. When you are updating a state property using its previous value, the callback argument must be used. This is due to the asynchronous nature of state updates. (See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous)
const increaseCount = () => {
setCount((count) => (count + 1));
};
It could probably be the reason why the count
was 3 instead of 4 as said by @Tim van Dam.
Upvotes: 1
Reputation: 20451
Most answers here are correct in explaining how the callback pattern of setState should be preferred when the updated state value depends on the previous state value. But one part of the question is still pending
But i click to 'Set 4' button my count value is still 4 but still component re-rendered.
I created this sandbox
and this indeed happens.
If we do setCount(4)
from increaseCount
and then from setFourValue
, both trigger a rerender.
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.
And React indeed does not go deeper into the tree, which you can check by uncommenting <Child>
. It is not going deeper into the tree as <Child>
will not rerender, even if <App>
does.
Upvotes: 0
Reputation: 465
To add on to Barry's answer, when you set the count to4
the first time with setFourValue
after increasing it to 4
with increaseCount
, it actually isn't 4. Console log the count and you'll see that it's actually 3
even though it displays 4
on the screen.
Upvotes: 1
Reputation: 10608
In React, components will only re-render if a state
or prop
in the component change.
Setting 4
to 4
is not a change.
React is smart enough to not re-render unnecessarily.
Upvotes: 1