React 使 useState 初始值有条件

use*_*977 5 javascript reactjs react-hooks

我正在尝试根据道具中的数据设置初始状态。

const Calculate({data}) => {
  const [number, setNumber] = data === 'end' ? useState(5) : useState(0);

  return (...)
}
Run Code Online (Sandbox Code Playgroud)

这给了我一个错误:React Hook“React.useState”被有条件地调用。React Hooks 必须在每个组件渲染中以完全相同的顺序调用。

所以我决定用 useEffect 更新我的代码:

const Calculate({data}) => {
  const [number, setNumber] = useState(0);

  useEffect(() => {
     if (data === 'end') {
       setNumber(5)
     }
   }, []);
} 
Run Code Online (Sandbox Code Playgroud)

但是,如果不需要,我宁愿不将状态最初设置为零。

或者我可以通过将初始值设为有条件来解决这个问题吗?

const Calculate({data}) => {
  const [number, setNumber] = useState(data === 'end' ? 5 : 0);

  return (...)
}
Run Code Online (Sandbox Code Playgroud)

这有什么副作用吗?为什么这个可行,而不是我最初的尝试?

Ris*_*abh 12

您可以在钩子中使用三元useState,它会正常工作。但是,最好按以下方式将其包装在函数表达式中。

const [number, setNumber] = useState((data) => data === 'end' ? 5 : 0)
Run Code Online (Sandbox Code Playgroud)

上面代码片段中的函数表达式在设置初始状态时只会被计算一次。将三元运算符包装在函数表达式内有一个好处。

假设data === 'end' ? 5 : 0您不想使用昂贵的计算结果来设置初始状态,在这种情况下您可以将其包装在函数表达式中,例如:

const [number, setNumber] = useState(() => expensiveFunction())
Run Code Online (Sandbox Code Playgroud)

这更好,因为() => expensiveFunction()将返回一个在初始渲染期间仅计算一次的函数。然而,如果您不将其包装expensiveFunction在函数表达式内,则每次组件渲染时都会对其进行求值,并阻止代码的执行,直到expensiveFunction返回一个值。

这种方法也称为Lazy initialization.


gio*_*gim 3

\n

这有什么副作用吗?为什么这会起作用而不是我最初的尝试?

\n
\n

不,没有副作用,这就是您的情况的方法。它在您的情况下不起作用,因为您违反了挂钩规则之一:

\n
\n

不要\xe2\x80\x99t 在循环、条件或嵌套函数内调用 Hooks。\n相反,请始终在 React 函数的顶层、\n在任何早期返回之前使用 Hooks。通过遵循此规则,您可以确保每次组件渲染时\n以相同的顺序调用 Hooks。\n这\n\xe2\x80\x99s 允许 React 在多个 useState 和 useEffect 调用之间\n正确保留 Hooks 的状态。(如果您\xe2\x80\x99很好奇,\n我们\xe2\x80\x99将在下面深入解释这一点。)

\n
\n

最初,您的useState调用本身被包装在一个条件中,这是一个问题。您的新方法不再是这种情况。

\n