19
loading...
This website collects cookies to deliver better user experience
useEffect
hook.function App(){
return 'Hello World';
}
const text = App();
console.log(text); // logs 'Hello World'
App
function in variable text
and displaying it in the console. We know that Javascript is single threaded and can execute only one line at a time. The flow of execution is top-to-bottom.text
variable. useEffect()
hook in a react component and explore when it is called and in what order.function App(){
React.useEffect(() => {
console.log('useEffect Ran!')
}, []);
return(
<div>Hello, World!</div>
)
}
[]
dependencies, you would have guessed that this hook runs only on mount (exactly like componentDidMount
). Yes, you are right, it runs just on the mount. so you would get this in consoleuseEffect Ran!
function App() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
console.log("Count Changed");
}, [count]);
return (
<button
onClick={() => {
setCount((c) => c + 1);
}}
>
{count}
</button>
);
}
[count]
dependency we would think this would run when the count
changes. count
would change, thus calling the useEffect hook right? lets check it out! Count Changed
componentDidUpdate
. If you have componentDidUpdate
it would still be called on the mount phase! If you are curious to know why the hooks are designed in this way, take a look at Fun with React Hooks in which Ryan Florence live codes useEffect
hook and explains why hooks should only be called in the top level of react component
count
changes.React.useEffect(() => {
console.log("Count Changed");
}, [count]);
Every hook in a component would be called on the mount phase (with or without the dependencies specified).
function Child() {
React.useEffect(() => {
console.log("Child useEffect Ran!");
return () => {
console.log("cleanUp of Child useEffect Ran!");
};
}, []);
return <div>Hello, From Child!</div>;
}
export default function App() {
const [showChild, setShowChild] = React.useState(false);
React.useEffect(() => {
console.log("useEffect Ran!");
return () => {
console.log("cleanUp of useEffect Ran!");
};
}, []);
return (
<div>
<div>Hello, World!</div>
{showChild ? <Child /> : null}
<button
onClick={() => {
setShowChild((b) => !b);
}}
>
{showChild ? "Hide" : "Show"} Child
</button>
</div>
);
}
App
component renders a Child
component which has useEffect with a cleanup function. This cleanup would be executed when the child component unmounts. So, When you render the component and toggle on the Hide/Show child button, You would get the corresponding logs as expected.function Child() {
React.useEffect(() => {
console.log("No Dependency!");
return () => {
console.log("cleanUp of No Dependency Ran!");
};
});
React.useEffect(() => {
console.log("Empty Dependency!");
return () => {
console.log("cleanUp of Empty Dependency Ran!");
};
}, []);
return <div>Hello, From Child!</div>;
}
When the component is unmounted, cleanup function from all the useEffects would be executed.
componentWillUnmount
this is the only part that would be executed on the unmount phase of that component.You can play around with the useEffect flow sandbox to see when each effect is getting called and its order.
App
running, and when you click on the Increment count button, before running the no deps hook, the cleanup function is executed.▶️ App Render Start
🛑 App Render End
App: useEffect no deps Cleanup 🧹
🌀 App: useEffect no deps
▶️ App Render Start
🛑 App Render End
▶️ Child Render Start
🛑 Child Render End
App: useEffect no deps Cleanup 🧹
🌀 CHILD: useEffect empty []
🌀 CHILD: useEffect no deps
🌀 App: useEffect no deps
React, when re-running an useEffect, it executes the clean up function before executing the hook.
useEffect
hook.