Last updated: Apr 6, 2024
Reading timeยท5 min
If you got the error "React Hook 'useEffect' is called conditionally error", click on the second subheading.
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.
Here is an example of how the error occurs.
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 issue is that we use the second useState
hook after a condition that may
return a value.
To solve the error, we must only call React hooks at the top level.
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> ); }
We moved the second useState
hook above the condition that might return a
value.
This means that we aren't allowed to use hooks inside loops, conditions or nested functions.
We should never call a hook conditionally.
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.
useState
call to the top level and not conditionally call the hook.Like the documentation states:
This helps React preserve the state of hooks between multiple useState
calls.
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.
Here is an example of how the error occurs.
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 issue in the code sample is that we are calling the useEffect
hook
conditionally.
useEffect
hookTo solve the error, we must only
call React hooks at the top level,
so we can move the condition inside of the useEffect
hook.
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> ); }
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.
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.
To solve the error, we have to move all hook calls above the condition that might return a value.
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> ); }
We moved the useEffect
hook above the condition that might return a value.
This means that we aren't allowed to use hooks inside loops, conditions or nested functions.
Like the documentation states:
This helps React preserve the state of hooks between multiple useState
and
useEffect
calls.