What the error? React: Rendered fewer hooks than expected. | Owen Conti

What the error? React: Rendered fewer hooks than expected.

Published on May 17, 2019 in category React.

๐Ÿ‘‹There's a video version of this post at the bottom of the page.

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.

function MyComponent(props) {
    if (props.id) {
        // BAD! Hooks cannot be used inside a conditional statement
        useEffect(() => {
            axios.get(`/api/data?id=${props.id}`);
        });
    }

    // ...render the component
}

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

function MyComponent(props) {
    if (props.loading) {
        return <Loading />;
    }

    const [state, setState] = useState(null)

    return (
        <div>My component markup here...</div>
    );
}

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:

function MyComponent(props) {
    useEffect(() => {
        if (props.id) {
            axios.get(`/api/data?id=${props.id}`);
        }
    }, [props.id]);

    // ...render the component
}

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!

๐Ÿ‘‹ Hi there! I hope you enjoyed this post. If you did, follow me on Twitter, @owenconti, for updates on new posts.

If you prefer to receive updates via email, subscribe to my newsletter where I send a weekly summary of the content I've released.

Feel free to check out other posts in the React category.