使用计算变量与 useState/useEffect 的后果

col*_*lby 5 javascript reactjs use-effect use-state

如果我有一个变量,其值可以根据另一个属性的值完全派生,那么初始化计算变量与使用useState/的组合useEffect来跟踪变量是否有任何后果/陷阱?让我用一个人为的例子来说明:

/**
 * ex paymentAmounts: [100, 300, 400]
 */
const Option1 = ({paymentAmounts}) => {
  const [average, setAverage] = useState(paymentAmounts.reduce((acc, curr) => curr + acc, 0) / paymentAmounts.length)

  useEffect(() => {
    setAverage(paymentAmounts.reduce((acc, curr) => curr + acc, 0) / paymentAmounts.length)
  }, [paymentAmounts])

  return (
    <div>
      Average: {average}
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

或者更简单地说

/**
 * ex paymentAmounts: [100, 300, 400]
 */
const Option2 = ({paymentAmounts}) => {
  const average = paymentAmounts.reduce((acc, curr) => curr + acc, 0) / paymentAmounts.length

  return (
    <div>
      Average: {average}
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

使用选项 2 我是否会放弃任何控制权和/或 React 优势?

Vue.js 似乎通过计算属性提供了此选项。

zhu*_*ien 1

useState当您想要在重新渲染之间跟踪组件中的某些内容(或在其子组件之间共享它)时,您可以使用状态(就像这样) 。在您的情况下,您将从父组件获取此“状态”(父组件是实际的状态持有者)。父状态的每次更改(在您的情况下)都会自动反映在您的子组件中。paymentAmounts

作为一般“规则”,不要对可计算的数据使用状态。请记住,状态跟踪变量的每次更改都会强制组件重新渲染。另一个不好的用法示例是这样的:

const Example = ({variable1}) => {
  const [variable, setVariable] = useState(variable1);

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

一些附加说明:

  1. 在您的第一个解决方案中,您通过使用引入了额外的开销 useEffect。正如已经指出的,当父组件的状态发生变化时,您的子组件将始终重新渲染并重新计算average
  2. 你的钩子用setAverage错了useEffect。setter 接受一个新值或一个接受当前值并返回新值的函数。
  3. 不确定您对paymentAmounts / paymentAmounts.length计算的期望。我想这只是一个虚拟代码,但如果不是,请查看它。您将数组本身(而不是其值的总和)除以它的长度。

所以,简而言之 - 是的,您应该使用一个简单的变量来计算平均值并放弃useState/ useEffect。您不仅没有放弃任何好处,而且实际上使您的代码更加高性能、可维护、可读且无错误。