'Number of console logs in component body not equal to number of rerenders?
I have a simple React component that is just supposed to console.log some dummy text when component is rendered. I have read some articles about rendering and I would assume that rendering happens at the same time as invoking the component, i.e. rendering is not possible without invoking/executing component function a priori.
So, the number of console logs in this case should be 2 for each - once when component initially renders, and second time when I click on the button and i is set to 2. Every next time React should be able to detect that state is actually not the same and not re-render the component.
But, I get "Hello from invoking" (that is not in use effect but in component body) three times, once when component initially renders, and two times when I click on the button. This component is for sure rendered just twice, so where did that third console.log come from? Is it possible that the component function is invoked, but not re-rendered? In contrary, "Hello from rendering" is logged twice as I would assume.
import { useEffect, useState } from "react";
const DummyComponent = (props) => {
const [i, setI] = useState(0);
useEffect(() => {
console.log("hello from rendering!");
});
console.log("hello from invoking!");
return (
<div onClick={() => setI(2)}}> Hello </div>
);
};
export default DummyComponent;
Solution 1:[1]
When the onClick calls setI, this causes a change to the state and an update gets triggered. This will call the lifecycle methods associated with an update.
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
The useEffect hook is called during componentDidUpdate() (as well as componentDidMount), while the console.log outside the useEffect is going to be called during render().
That means we should expect to see 1 hello from rendering! and 1 hello from invoking! when we refresh or when we click the "Hello" div.
In this codesandbox example you can see that we are getting the expected behavior of one a single console.log of each.
Now in this codesandbox example we are using StrictMode, and you can see that when we click the "Hello", we are seeing hello from rendering! 1 time, but we are seeing hello from invoking! 2 times!
StrictMode was enabled by adding a <StrictMode> tag to index.js
root.render(
<StrictMode>
<App />
</StrictMode>
);
It seems that the behavior you are describing is coming from the use of StrictMode.
This happens because StrictMode intentionally double-invokes the following functions:
- Class component constructor, render, and shouldComponentUpdate methods
- Class component static getDerivedStateFromProps method
- Function component bodies
- State updater functions (the first argument to setState)
- Functions passed to useState, useMemo, or useReducer
Thus, we see the render function occurring 2 times, and we get the 2 console.logs.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
