React Hook 'useState' is called conditionally error [Fixed]

avatar
Borislav Hadzhiev

Last updated: Apr 6, 2024
5 min

banner

# Table of Contents

  1. React Hook 'useState' is called conditionally error
  2. React Hook 'useEffect' is called conditionally error

If you got the error "React Hook 'useEffect' is called conditionally error", click on the second subheading.

# React Hook 'useState' is called conditionally error

The error "React hook 'useState' is called conditionally" occurs when we use the useState hook conditionally or after a condition that may return a value.

To solve the error, move all React hooks above any conditionals that may return a value.

react hook usestate called conditionally

Here is an example of how the error occurs.

App.js
import React, {useState} from 'react'; export default function App() { const [count, setCount] = useState(0); if (count > 0) { return <h1>Count is greater than 0</h1>; } // โ›”๏ธ React Hook "useState" is called conditionally. //React Hooks must be called in the exact same order // in every component render. Did you accidentally call // a React Hook after an early return? const [message, setMessage] = useState(''); return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
The code for this article is available on GitHub

The issue is that we use the second useState hook after a condition that may return a value.

# Only call React hooks at the top level

To solve the error, we must only call React hooks at the top level.

App.js
import React, {useState} from 'react'; export default function App() { const [count, setCount] = useState(0); // ๐Ÿ‘‡๏ธ Move hooks above condition that might return const [message, setMessage] = useState(''); // ๐Ÿ‘‡๏ธ Any conditions that might return must be below all hooks if (count > 0) { return <h1>Count is greater than 0</h1>; } return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }

only call react hooks at top level

The code for this article is available on GitHub

We moved the second useState hook above the condition that might return a value.

This solves the error because we have to ensure that React hooks are called in the same order each time a component renders.

This means that we aren't allowed to use hooks inside loops, conditions or nested functions.

# Don't call React hooks conditionally

We should never call a hook conditionally.

App.js
import React, {useState} from 'react'; export default function App() { const [count, setCount] = useState(0); if (count === 0) { // โ›”๏ธ React Hook "useState" is called conditionally. // React Hooks must be called in the exact same order in every component render. const [message, setMessage] = useState(''); } return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }

The code snippet causes the error because we are calling the second useState hook conditionally.

This is not allowed because the number of hooks and the order of hook calls have to be the same on re-renders of our function components.

To solve the error, we have to move the useState call to the top level and not conditionally call the hook.

Like the documentation states:

  • Only call hooks at the top level
  • Don't call hooks inside loops, conditions or nested functions
  • Always use hooks at the top level of your React function, before any early returns
  • Only call hooks from React function components or from custom hooks.

This helps React preserve the state of hooks between multiple useState calls.

# React Hook 'useEffect' is called conditionally error

The error "React hook 'useEffect' is called conditionally" occurs when we use the useEffect hook conditionally or after a condition that may return a value.

To solve the error, move all React hooks above any conditionals that may return a value.

react hook useeffect called conditionally

Here is an example of how the error occurs.

App.js
import React, {useEffect, useState} from 'react'; export default function App() { const [count, setCount] = useState(0); if (count > 0) { // โ›”๏ธ React Hook "useEffect" is called conditionally. // React Hooks must be called in the exact same order in every component render. useEffect(() => { console.log('count is greater than 0'); }, [count]); } return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
The code for this article is available on GitHub

The issue in the code sample is that we are calling the useEffect hook conditionally.

# Move the condition inside the useEffect hook

To solve the error, we must only call React hooks at the top level, so we can move the condition inside of the useEffect hook.

App.js
import React, {useEffect, useState} from 'react'; export default function App() { const [count, setCount] = useState(0); useEffect(() => { // ๐Ÿ‘‡๏ธ Move condition in hook if (count > 0) { console.log('count is greater than 0'); } }, [count]); return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }

move condition inside use effect hook

Moving the if statement inside of the useEffect hook helps, because the hook is now at the top level and has predictable behavior that allows React to correctly preserve the state between useState and useEffect calls.

Another cause of the error is when we call the useEffect hook after a conditional that may return a value.

App.js
import React, {useEffect, useState} from 'react'; export default function App() { const [count, setCount] = useState(0); // ๐Ÿ‘‡๏ธ might return before useEffect is called if (count > 0) { return <h1>Count is greater than 0</h1>; } // โ›”๏ธ React Hook "useEffect" is called conditionally. // React Hooks must be called in the exact same order in every component render. // Did you accidentally call a React Hook after an early return? useEffect(() => { console.log('count is greater than 0'); }, [count]); return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }

The issue here is that the useEffect hook is called after a condition that may return a value.

# Move all hook calls above the conditions that might return a value

To solve the error, we have to move all hook calls above the condition that might return a value.

App.js
import React, {useEffect, useState} from 'react'; export default function App() { const [count, setCount] = useState(0); // ๐Ÿ‘‡๏ธ Moved hook above condition that may return useEffect(() => { console.log('count is greater than 0'); }, [count]); // ๐Ÿ‘‡๏ธ Condition that may return is below all hooks if (count > 0) { return <h1>Count is greater than 0</h1>; } return ( <div> <h2>Count: {count}</h2> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }

move all hook calls above conditions that might return value

The code for this article is available on GitHub

We moved the useEffect hook above the condition that might return a value.

This solves the error because we have to ensure that React hooks are called in the same order each time a component renders.

This means that we aren't allowed to use hooks inside loops, conditions or nested functions.

Like the documentation states:

  • Only call hooks at the top level
  • Don't call hooks inside loops, conditions or nested functions
  • Always use hooks at the top level of your React function, before any early returns
  • Only call hooks from React function components or from custom hooks.

This helps React preserve the state of hooks between multiple useState and useEffect calls.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev