Fix the "React Hook is Called Conditionally" Error in React
Nick Scialli
March 16, 2021
New — Check out my free newsletter on how the web works!
If you’re new to React hooks, you might find yourself encountering this somewhat cryptic error. Let’s dive into what it is and how to fix it.
What Does It Mean?
The first rule of hooks reads as follows:
Only Call Hooks at the Top Level
Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
The TL;DR here is that you can’t use any hooks after you return
early from a component, inside a loop, or inside a conditional.
Why Does It Happen?
There’s a good chance your component looks either like this:
Example 1
function MyComponent() {
if (someCondition) {
return <p>Some information</p>;
}
useEffect(() => {
// Do something
}, []);
return <p>Some other information</p>;
}
Or like this:
Example 2
function MyComponent() {
if (someCondition) {
useEffect(() => {
// Do something
}, []);
}
return <p>Some other information</p>;
}
Or even like this:
Example 3
function MyComponent() {
myArray.forEach((el) => {
useEffect(() => {
// Do something
}, []);
});
return <p>Some other information</p>;
}
Each of these examples breaks the first rule of hooks!
- Example 1 returns early before the
useEffect
hook is called - Example 2 calls the
useEffect
hook inside a conditional - Example 3 calls the
useEffect
hook inside a loop
How To Fix The Error
The solution is a bit idosyncratic to the particular use case, but generally I see Examples 1 and 2 above a lot. Usually, you are tying to make sure an effect doesn’t run under certain conditions.
Conditionally Running Effects
Since hooks have to run on each component render, you technically can’t conditionally run a useEffect
hook. But, you can conditionally return early inside the useEffect
hook.
Let’s see how that would look.
function MyComponent() {
useEffect(() => {
if (someCondition) {
return;
}
// Do something only when `someCondition` is falsey
}, []);
return <p>Some other information</p>;
}
And that’s it— you are now running the hook on every render (as required) but you’re still able to bail out early inside that hook if you need to.
🎓 Learn how the web works
One of the best ways to level up your tech career is to have a great foundational understanding of how the web works. In my free newsletter, How the Web Works, I provide simple, bite-sized explanations for various web topics that can help you boost your knowledge. Join 2,500+ other learners on the newsletter today!
Signing up is free, I never spam, and you can unsubscribe any time. You won't regret it!
Sign up for the newsletter »Nick Scialli is a senior UI engineer at Microsoft.