'React Hooks: Why I have this output?
I'm studying React hooks but i am not able to understand why I got this output in the console. Someone with great heart could explain in detail the "running execution" oh these hooks?
import { useState, useEffect } from "react";
function Homepage() {
const [state, setState] = useState();
useEffect(() => {
console.log("useEffect");
console.log("useEffect not executed");
setState("hello")
}, []);
if (!state) {
console.log("state not defined");
return <div>State undefined</div>;
}
return <div>ciao</div>;
}
export default Homepage;
console output: state not defined state not defined useEffect useEffect not executed useEffect useEffect not executed
Solution 1:[1]
Basically it's a combination of React.StrictMode double invoking the function body twice as a way to help you detect unexpected side-effects
Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:
- Class component
constructor,render, andshouldComponentUpdatemethods- Class component static
getDerivedStateFromPropsmethod- Function component bodies <-- this
- State updater functions (the first argument to
setState)- Functions passed to
useState,useMemo, oruseReducer
remounting the component to ensure reusable state
To help surface these issues, React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.
and the useEffect hook being called at the end of the render cycle.
function Homepage() {
const [state, setState] = useState();
useEffect(() => {
console.log("useEffect"); // logs second as expected side-effect
console.log("useEffect not executed");
setState("hello");
}, []);
if (!state) {
console.log("state not defined"); // logs first as unintentional side-effect
return <div>State undefined</div>;
}
return <div>ciao</div>;
}
...
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import Homepage from "./Homepage";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<StrictMode>
<Homepage />
</StrictMode>
);
Explaining the logs
console output:
state not defined // <-- initial render
state not defined // <-- double invocation of function body
useEffect // <-- effect at end of initial render
useEffect not executed // <-- effect at end of initial render
...unmount/mount
useEffect // <-- effect at end of render
useEffect not executed // <-- effect at end of render
Solution 2:[2]
useEffect runs when the page renders and the other functions execute before useEffect so your code runs the if (!state) first then useEffect runs and state sets to "hello"; here is a link to fully understand useEffect hook: useEffect; Good luck;
Solution 3:[3]
your if statement is running before the useEffect even tho is after it, you need to put both divs inside the return and remove the if
return (
{!state ? <div>State undefined</div> : <div>ciao</div>}
)
Solution 4:[4]
state not definedfirst render of your component Homepagestate not defined2nd renderuseEffect useEffect not executedyour component is mounted, so the useEffect hook is triggered.useEffect useEffect not executedhere your component rerender with the statehellothe useEffect hook is triggered again
In practice, useEffect hook runs at minimum following your dependency array. Here your set [] so the useEffect hook runs when the component mounts, but sometimes it can still be triggered.
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 | |
| Solution 2 | Ali Navidi |
| Solution 3 | c0dm1tu |
| Solution 4 | Frédéric Lang |
