Owen Conti

"Rendered fewer hooks than expected." ReactJS error

Posted on under React by Owen Conti.

In React, hooks must be called during render, and they must be called unconditionally and in the same order every render.

This means if you have a conditional if statement in your render logic, hooks cannot be within the conditional branch.

1function MyComponent(props) {
2 if (props.id) {
3 // BAD! Hooks cannot be used inside a conditional statement
4 useEffect(() => {
5 axios.get(`/api/data?id=${props.id}`);
6 });
7 }
8 
9 // ...render the component
10}

It also means that you cannot use hooks after your conditional statement, if your conditional statement returns early, ie:

1function MyComponent(props) {
2 if (props.loading) {
3 return <Loading />;
4 }
5 
6 const [state, setState] = useState(null)
7 
8 return (
9 <div>My component markup here...</div>
10 );
11}

In this case, if the loading prop is true, our component will return early resulting in the hook sometimes being called instead of always being called.

Okay, so what if I need to conditionally call a hook?

You can move the conditional logic inside of the hook:

1function MyComponent(props) {
2 useEffect(() => {
3 if (props.id) {
4 axios.get(`/api/data?id=${props.id}`);
5 }
6 }, [props.id]);
7 
8 // ...render the component
9}

The key is to make sure that all hooks you use are called every render, because React is tracking the hook calls (and their order!) behind the scenes.


Thanks for reading this article!

Hopefully you found this article useful! If you did, share it on Twitter!

Found an issue with the article? Submit your edits against the repository.