【问题标题】:React make useState initial value conditionalReact 使 useState 初始值有条件
【发布时间】:2021-10-26 21:36:54
【问题描述】:

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

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

  return (...)
}

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

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

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

  useEffect(() => {
     if (data === 'end') {
       setNumber(5)
     }
   }, []);
} 

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

或者我可以通过使初始值有条件来解决它吗?

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

  return (...)
}

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

【问题讨论】:

  • 做你想做的事的惯用方式是const [number, setNumber] = useState(data == 'end' ? 5 : 0)
  • React 是痛苦的,你有没有尝试过像baby feather Solid 一样的超快速和轻量级?

标签: javascript reactjs react-hooks


【解决方案1】:

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

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

不要在循环、条件或嵌套函数中调用 Hooks。 相反,总是在你的 React 函数的顶层使用 Hooks, 在任何提前返回之前。通过遵循此规则,您可以确保 每次渲染组件时,都会以相同的顺序调用挂钩。 这就是让 React 正确保存 Hooks 状态的原因 在多个 useState 和 useEffect 调用之间。 (如果你好奇, 我们将在下面深入解释这一点。)

最初您的useState 调用它们自己被包裹在一个条件中,这是一个问题。您的新方法不再是这种情况了。

【讨论】:

    【解决方案2】:

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

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

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

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

    const [number, setNumber] = useState(() => expensiveFunction())
    

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

    这种方法也称为Lazy initialization

    【讨论】:

      【解决方案3】:

      如果数据可以改变...... 您唯一需要确保自己处理的是传递下来的数据不是null,而是undefined(如果它不存在)。

      您的useEffect 应该在依赖数组中有data,以便在发生任何更改时重新渲染组件。

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

      【讨论】:

        猜你喜欢
        • 2020-03-08
        • 2021-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-22
        • 1970-01-01
        • 2014-03-14
        相关资源
        最近更新 更多