代码之家  ›  专栏  ›  技术社区  ›  Bhojendra Rauniyar

componentWillReceiveProps与getDerivedStateFromProps

  •  5
  • Bhojendra Rauniyar  · 技术社区  · 7 年前

    对于我来说,究竟什么样的组件将接收props和getDerivedStateFromProps是一个微妙的问题。因为,我在使用getDerivedStateFromProps时遇到了一个问题:

    // Component 
    state = {
      myState: []
    }
    
    // Using this method works fine:
    
    componentWillReceiveProps(nextProps) {
      this.setState({
        myState: nextProps.myPropsState
      })
    }
    
    // But using this method will cause the checkboxes to be readonly:
    
    static getDerivedStateFromProps(nextProps,prevProps) {
      const { myPropsState: myState } = nextProps
      return {
        myState
      }
    }
    
    // And here's checkbox
    <input type="checkbox" id={`someid`} 
     onChange={(e) => this.handleMethod(e, comp.myState)} 
     checked={myState.indexOf(comp.myState) > -1} />
    

    React版本:16.4.1

    3 回复  |  直到 7 年前
        1
  •  4
  •   Shubham Khatri    7 年前

    getDerivedStateFromProps 不是直接替代 componentWillReceiveProps ,纯粹是因为它在每次更新后都会被调用,无论是状态的更改、道具的更改还是父级的重新呈现。

    不管是什么情况,只要从 getDerivedStateFromProps 不是正确的方法,您需要在返回值之前比较状态和道具。否则每次更新时,状态都会重置为props并继续循环

    根据 docs

    getDerivedStateFromProps 在调用呈现之前调用 方法,无论是在初始装载还是在后续更新时。它应该 返回对象以更新状态,或 null 什么都不更新。

    这种方法存在于罕见的用例依赖于状态的情况下。 道具随时间变化。例如,它可能很方便 实现 <Transition> 比较其上一个和 下一个孩子来决定他们中的哪一个来做动画。

    派生状态会导致冗长的代码并使组件 很难想象。确保你熟悉simpler 选择:

    如果你需要的话 产生副作用 (例如,数据获取 或者动画)为了响应道具的变化,使用 componentDidUpdate 而是生命周期。

    如果你想的话 只有当道具改变时才重新计算一些数据 ,使用 一 memoization 而是帮手。

    如果你想的话 当道具改变时重置某些状态 ,考虑 或者做一个组件 fully controlled fully uncontrolled with a key instead .

    附笔。 注意getDerivedStateFromProps的参数是 props state 而不是 nextProps and 前支柱`

    为了了解更多细节,

    为了根据props的变化进行更改,我们需要将prevPropsState存储在state中,以便检测更改。典型的实现看起来像

    static getDerivedStateFromProps(props, state) {
        // Note we need to store prevPropsState to detect changes.
        if (
          props.myPropsState !== state.prevPropsState
        ) {
          return {
            prevPropsState: state.myState,
            myState: props.myPropsState
          };
        }
        return null;
      }
    
        2
  •  0
  •   trixn    7 年前

    从react文档:

    注意,此方法被激发 每次渲染时 不管是什么原因。这与 UNSAFE_componentWillReceiveProps ,仅当父对象导致重新渲染而不是本地 setState .

    每次调用后,您都有效地使用当前道具覆盖您的状态 setState() . 所以当你选中一个复选框 (e) => this.handleMethod(e, comp.myState) 被称为假设调用 设置状态() 更新复选框的选中状态。但在那之后 getDerivedStateFromProps() 将被调用( 渲染前 )这又恢复了这种变化。这就是为什么 unconditionally updating state from props is considered an anti-pattern .

        3
  •  0
  •   Bhojendra Rauniyar    7 年前

    最后,我解决了我的问题。这是一次痛苦的调试:

    // Child Component
    
    // instead of this
    // this.props.onMyDisptach([...myPropsState])
    
    // dispatching true value since myPropsState contains only numbers
    this.props.onMyDispatch([...myPropsState, true])
    

    这是因为,我有两个条件:1)在复选框上更改(组件)2)在重置按钮上按下(子组件)

    当按下重置按钮时,我需要重置状态。所以,在将状态分派给props for reset按钮时,我使用了一个布尔值来知道它与reset不同。你可以使用任何你喜欢的东西,但需要跟踪。

    现在,在组件中,我在调试控制台输出后发现了一些关于组件willreceiveprops和getDerivedStateFromProps之间差异的提示。

    // Component
    static getDerivedStateFromProps(props, state) {
        const { myPropsState: myState } = props
        // if reset button is pressed
        const true_myState = myState.some(id=>id===true)
        // need to remove true value in the store
        const filtered_myState = myState.filter(id=>id!==true)
        if(true_myState) {
          // we need to dispatch the changes to apply on its child component
          // before we return the correct state
          props.onMyDispatch([...filtered_myState])
          return {
            myState: filtered_myState
          }
        }
        // obviously, we need to return null if no condition matches
        return null
      }
    

    下面是控制台输出的结果:

    • 每当属性更改时,getDerivedStateFromProps会立即记录日志

    • componentWillReceiveProps日志只有在子传播props更改之后

    • getDerivedStateFromProps不响应props更改(我指的是调度更改,如示例代码中所示)

    • 组件将接收道具对道具更改的响应

    • 因此,我们需要在使用getDerivedStateFromProps时提供对子组件的更改。

    在我需要的状态中粘贴真值的过程,因为getDerivedStateFromProps处理所有更改,而componentWillReceiveProps只处理子组件将更改分派给props。

    顺便说一下,如果getDerivedStateFromProps,您可以使用custom属性检查它是否已更改,并更新值,但出于某种原因,我必须调整此技术。

    我的措辞可能有些混乱,但我希望你能理解。