Prelude
I know that rendering state changes right after the component mounts should be put into a useEffect hook with an empty dependency array to be rendered, for example:
const [value, setValue] = useState("one");
useEffect(() => {
setValue("two");
}, []);
Scenario
Out of curiosity I created a component (i.e. this CodeSandbox) with a global variable isFirstRender which checks whether it's the first render to change state for the initial mount of the component:
let isFirstRender = true;
export default function App() {
const [value, setValue] = useState("one");
// should only run once at the beginning
if (isFirstRender) {
console.log("inside if clause");
setValue("two");
isFirstRender = false;
}
useEffect(() => {
console.log("mounted");
}, []);
console.log("-- render --", { value });
return (
<div className="App">
<h1>Conditional useState setters</h1>
<p>Value: {value}</p>
</div>
);
}
Stack Snippet:
const {useState, useEffect} = React;
let isFirstRender = true;
/*export default*/ function App() {
const [value, setValue] = useState("one");
// should only run once at the beginning
if (isFirstRender) {
console.log("inside if clause");
setValue("two");
isFirstRender = false;
}
useEffect(() => {
console.log("mounted");
}, []);
console.log("-- render --", { value });
return (
<div className="App">
<h1>Conditional useState setters</h1>
<p>Value: {value}</p>
</div>
);
}
ReactDOM.render(<React.StrictMode><App /></React.StrictMode>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
To my surprise the component function gets invoked and the changed value ("two" instead of "one") is visible in the console, but won't render to the screen. It still says "one" in the browser.
Questions
Doesn't the fact that the function is being invoked by the call of the setter function of the
useStatehook mean that the function "does" render with the updated state value?I thought in React an invocation of a function component is synonymous of a render? Is the time before a component gets mounted an exception to this rule?