头图

The text starts here~

Overview

"React hook 'useState' is called conditionally" error occurs when we conditionally use useState hook, or after a condition that may have a return value. To fix the bug, move all React hooks above any conditions that might return a value.

react-hook-usestate-called-conditionally.png

Here is an example to show 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 problem with the above snippet is that we are using the second useState hook after a condition that may have a return value.

top-level call

To fix that, we have to call React hooks at the very 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 where it might return a value.

This solves the error because we have to make sure that every time the component renders, the React hooks are called in the same order.

This means we are not allowed to use hooks inside loops, conditionals or nested functions.

We should never call hooks 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 snippet above caused the error because we conditionally called the second useState hook.

This is not allowed because the number of hooks and the order in which the hooks are called, must be the same in the re-render of our function component.

To fix this bug, we had to move the call to useState to the top level instead of calling this hook conditionally.

As the documentation says:

  • Only use hooks at the top level
  • Don't call Hooks in loops, conditionals or nested functions
  • Make sure to always use Hook at the top level of your React function and before any return
  • Calling Hooks in React's Function Components
  • Call other Hooks in custom Hooks

chuck
303 声望41 粉丝