export const App = (props) => {
const [data, setData] = useState(0)
console.log(data)
const onClick = () => {
setData(1)
}
return <button onClick={onClick}>button</button>
}
From the above example, When I click button more than 2 times, I got result.
And also this code is not in <StrictMode>
0
1
1
(‘1’ printed twice even though setState same value)
Reproduced here ~ https://codesandbox.io/s/bold-glitter-zphpwr?file=/src/App.js
You can see that the render count doesn’t increase but there’s one extra log line for console.log("1: ", data)
Same result in below example.
export const App = (props) => {
const [data, setData] = useState(0)
console.log(data)
useEffect(() => {
setData(1)
}, [data])
return <></>
}
and In other case below, I got infinite loop.
export const App = (props) => {
const [data, setData] = useState(0)
console.log(data)
setData(1)
return <button onClick={onClick}>button</button>
}
I don’t know why the result came out like this.
2
Answers
Adding some extra logging shows what’s going on…
You can see that clicking the button a second time causes the following to be logged
However the displayed
renderCountRef.current
doesn’t move beyond2
.React appears to be executing a render but then determines nothing needs to change and discards the result.
From the (legacy) docs
Just like how
<StrictMode>
causes your effect hooks to execute multiple times, your app should be resilient to extra renders.This is React’s expected behaviour. React tries to bail out of useless renders. But there might be times that it cannot judge it and would re-render anyway to be safe.
From the legacy docs:
Look at this sandbox. Here I have updated your code to add a child component. As you can see even though there is an `un-necessary’ re-render on the parent. The update is not going deeper into the tree.