用计算字段反应状态

Phi*_*nin 4 javascript state reactjs

我有一个反应组件,它具有属性和状态。一些状态字段包含输入数据(从输入控件中提升),但状态中的某些字段也必须根据当前状态和属性进行计算:

在此处输入图片说明

问题:更新状态的计算字段的最佳方法是什么(基于状态和道具的其他字段)?

这样做的丑陋方式:

componentDidUpdate(){
    this.setState({calculatedField:calculate(this.props,this.state)})) 
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我将获得无限循环的更新,或者在最佳情况下(如果使用PureComponent,则是)双重渲染调用。

到目前为止,我发现的最佳解决方案(但仍然很丑):创建一个calculated处于状态的对象,该对象包含计算所得的字段并在componentWillUpdate中进行更新,避免使用setState:

componentWillUpdate(nextProps,nextState){
   nextState.calculated.field1=f(nextProps,nextState)
}
Run Code Online (Sandbox Code Playgroud)

componentDidUpdate(){
    this.setState({calculatedField:calculate(this.props,this.state)})) 
}
Run Code Online (Sandbox Code Playgroud)
componentWillUpdate(nextProps,nextState){
   nextState.calculated.field1=f(nextProps,nextState)
}
Run Code Online (Sandbox Code Playgroud)

这也是丑陋的解决方案,不建议React避免setState来改变状态。那么什么是正确的解决方案呢?

注意:

在我的真实应用程序中,由于渲染实际上是复杂的对象,因此无法在渲染过程中每次都重新计算f(a,b),因此我需要以某种方式对其进行缓存,并且最好的方式是处于状态。

elq*_*sta 5

如果您使用的是React 16.8.0及更高版本,则可以使用React hooks API。我认为这useMemo()可能是您需要的。例如:

import React, { useMemo } from 'react'

const MyComponent = ({ ...props }) => {
  const calculatedValue = useMemo(
    () => {
      // Do expensive calculation and return.
    },
    [a, b]
  )

  return (
    <div>
      { calculatedValue }
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅React文档。

  • 这应该是公认的答案。它解决了重新计算的性能问题,这正是引发原始问题的原因。它比将其存储在状态中更好,因为正如Ole所述,它可以保护您避免直接更改计算值。 (3认同)

Cha*_*nda 0

您的第一次尝试是解决此问题的正确方法。但是,您需要添加检查以查看状态是否确实发生了变化:

componentDidUpdate(prevProps, prevState){
    if(prevState.field !== this.state.field){
        this.setState({calculatedField:calculate(this.props,this.state)})) 
    }
}

shouldComponentUpdate(nextProps, nextState) {
    return this.state.calculatedField !== nextState.calculatedField
}
Run Code Online (Sandbox Code Playgroud)

您需要检查在计算方法中使用的状态和道具,并确保它们在再次更新状态之前已更改。这将防止无限循环。