In React, if a child component and a parent component both have useEffect hooks, why does the child component’s useEffect hook execute before the parent’s?
import React, { useState, useEffect } from "react";
function Parent() {
useEffect(() => {
console.log("Parent useEffect");
// Perform some side effect logic
}, []);
return (
<div>
<h1>Parent Component</h1>
<Child/>
</div>
);
}
function Child() {
useEffect(() => {
console.log("Child useEffect");
// Perform some side effect logic
}, []);
return (
<div>
<h2>Child Component</h2>
</div>
);
}
export default function App() {
return (
<div className="App">
<Parent />
</div>
);
}
In React, if a child component and a parent component both have useEffect hooks, I expect it is possible to make the parent component’s useEffect hook execute before the child’s.
3
Answers
I think that you could do something like the following:
This records whether the parent has completed its useEffect in state, passes that down to the child, uses the child’s useEffect dependency array to decide whether to run or not.
For your original example I think we can check that it is running the child useEffect first:
Edit:
According to the React documentation, the
useEffect
is called during the mount: https://react.dev/reference/react/useEffect. The parent useEffect should be called before the child one. The reason you see the console of child one is probably because of the console.log which is an async function: https://nodejs.org/api/async_hooks.html#printing-in-asynchook-callbacksNot sure it exists a real "clean" solution for that. What would be your use case?
A workaround would be to render conditionally the child so the condition is the execution of the parent
useEffect
One potential solution is to swap the parent’s
useEffect
with auseLayoutEffect
.Example:
The reason this works is because, as mentioned in the
documentation
:This would do the trick, but usually this type of situation points to some antipattern.
And either way you are creating an implicit dependency here, which is not really advised.
So I suggest to first re-think this and try to figure out if there is a more straightforward way to achieve whatever it is you’re trying to achieve.