【问题标题】:How to check what props changed in componentWillReceiveProps如何检查 componentWillReceiveProps 中的哪些道具发生了变化
【发布时间】:2016-12-03 22:20:33
【问题描述】:

有没有办法检查 componentWillReceiveProps 内的哪些道具发生了变化(而不是将旧道具存储在其他地方)?

componentWillReceiveProps (newProps) {
  if( /* newProps.profileImage is different to previous props */ ) /* do stuff */
}

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    您仍然可以与this.props.profileImage 进行比较,因为在调用componentWilReceiveProps 之前它不会更新。比如docs中,就使用了这个例子:

    componentWillReceiveProps: function(nextProps) {
      this.setState({
        likesIncreasing: nextProps.likeCount > this.props.likeCount
      });
    }
    

    【讨论】:

      【解决方案2】:

      请注意,函数 componentWillReceiveProps 现在已弃用。引用the official documentation:

      如果您使用componentWillReceiveProps 仅重新计算某些数据 当 prop 发生变化时,请改用 memoization helper。

      这是指您在componentWillReceiveProps 中的检查是为了避免不必要地多次重新计算同一事物。在linked blog post 中,它建议缓存昂贵函数的结果,以便可以查找它,而不是重新计算。这可以使用诸如memoize-one 之类的帮助程序来完成。

      如果您使用componentWillReceiveProps 来“重置”某些状态 道具更改,请考虑使组件完全受控或 取而代之的是完全不受控制。

      同样,linked blog post 更详细地描述了这一点,但简而言之:

      • “完全受控”组件是指没有状态的功能组件(父组件负责处理状态)。
      • “完全不受控制”的替代方案是使用props 设置初始状态,然后忽略对道具的所有进一步更改。李>

      在极少数情况下,您可能需要使用 getDerivedStateFromProps 生命周期作为最后的手段。

      此函数接收(props, state) 并将任何更改返回到调用render 之前的状态,让您可以控制做任何您想做的事情。


      原始答案,适用于旧版本的 React

      在这个lifecycle method被调用的时间点,this.props指的是之前的一组props。

      要将新道具上的单个属性foo 与旧道具上的相同属性进行比较,您只需将newProps.foothis.props.foo 进行比较即可。所以在你的例子中:

      componentWillReceiveProps (newProps) {
        if( newProps.profileImage !== this.props.profileImage ) /* do stuff */
      }
      

      【讨论】:

        【解决方案3】:

        是的,您可以检查特定道具是否发生了变化。 this.props 指的是他们改变之前的道具之前。比如:

        componentWillReceiveProps(newProps) {
          if( newProps.profileImage != this.props.profileImage ) {
            /* do stuff */
          }
        }
        

        注意: props 不一定会在每次调用方法时都改变,所以值得测试看看哪个 props 改变了。

        【讨论】:

          【解决方案4】:

          你还可以循环遍历所有的 props,看看有什么变化。

          componentWillReceiveProps(nextProps) {
            for (const index in nextProps) {
              if (nextProps[index] !== this.props[index]) {
                console.log(index, this.props[index], '-->', nextProps[index]);
              }
            }
          }
          

          【讨论】:

            【解决方案5】:

            从 React 16.3 开始,不推荐使用 componentWillReceiveProps,请参考 react 网站上的 unsafe_componentwillreceiveprops 文档。

            改用getDerivedStateFromProps

            static getDerivedStateFromProps(nextProps, prevState) {
              if(nextProps.profileImage !== prevState.profileImage ) {
                return {stateFoo: 'valueBar'};
              }
            }
            

            返回值的行为类似于setState

            【讨论】:

            • getDerivedStateFromProps 的第二个参数是之前的 state 而不是props 的之前的状态。这仅在您将要检查的道具复制到状态时才有效。
            • 方法的正确合约是getDerivedStateFromProps(props, state) 无法访问之前的道具或状态
            【解决方案6】:

            就像给将来发现此内容的任何人的说明一样。看来 componentWillReceiveProps() 将被弃用。文档现在建议您使用 getDerivedStateFromProps()。关于原因的解释可以在这里找到:https://reactjs.org/blog/2018/03/29/react-v-16-3.html#component-lifecycle-changes

            【讨论】:

              【解决方案7】:

              你应该实现这样的逻辑:

              import React from 'react';
              import { View, Dimensions } from 'react-native';
              class DataTable extends React.Component {
                state = {
                    previousProps: null // Keep snapshot of current props in State & never change this through setState()
                }
              
                static getDerivedStateFromProps(props, currentState) {
                    if (JSON.stringify(props) === JSON.stringify(currentState.previousProps)){
                        //Here it's mean that props are not changed!!!
                        return null;
                    }
              
                    //Here it's mean props are changed!
                    //Here You find out what are changed through looping
                    //Don't forget to return new props as a state here!
                    return {
                        previousProps: props,
                        //...Pass your new state depending on new props here!
                    }
              
                }
              
              
                render() {
                    return(
                        <View>
                             {...}
                        </View>
                    )
                }
              }
              
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-02-10
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多