Javascript 如何使用生命周期方法getDerivedStateFromProps而不是componentWillReceiveProps

Javascript 如何使用生命周期方法getDerivedStateFromProps而不是componentWillReceiveProps,javascript,reactjs,lifecycle,Javascript,Reactjs,Lifecycle,在即将发布的版本中,组件将接受props将被完全淘汰,取而代之的是一种新的生命周期方法getDerivedStateFromProps: 经检查,您现在似乎无法直接比较此.props和下一步操作,就像您在组件中将接收props一样。这有什么办法吗 此外,它现在返回一个对象。假设返回值本质上是this.setState,对吗 下面是我在网上找到的一个示例: 之前 class ExampleComponent extends React.Component { state = { der

在即将发布的版本中,
组件将接受props
将被完全淘汰,取而代之的是一种新的生命周期方法
getDerivedStateFromProps

经检查,您现在似乎无法直接比较
此.props
下一步操作
,就像您在
组件中将接收props一样。这有什么办法吗

此外,它现在返回一个对象。假设返回值本质上是this.setState
,对吗

下面是我在网上找到的一个示例:

之前

class ExampleComponent extends React.Component {
  state = {
    derivedData: computeDerivedState(this.props)
  };

  componentWillReceiveProps(nextProps) {
    if (this.props.someValue !== nextProps.someValue) {
      this.setState({
        derivedData: computeDerivedState(nextProps)
      });
    }
  }
}
之后

class ExampleComponent extends React.Component {
  // Initialize state in constructor,
  // Or with a property initializer.
  state = {};

  static getDerivedStateFromProps(nextProps, prevState) {
    if (prevState.someMirroredValue !== nextProps.someValue) {
      return {
        derivedData: computeDerivedState(nextProps),
        someMirroredValue: nextProps.someValue
      };
    }

    // Return null to indicate no change to state.
    return null;
  }
}

关于删除
组件WillReceiveProps
:您应该能够通过组合使用
getDerivedStateFromProps
componentDidUpdate
来处理其使用,请参见迁移示例。是的,
getDerivedStateFromProps
返回的对象更新状态类似于传递给
setState
的对象

如果您确实需要道具的旧值,您可以始终使用以下内容将其缓存在您的状态中:

state = {
  cachedSomeProp: null
  // ... rest of initial state
};

static getDerivedStateFromProps(nextProps, prevState) {
  // do things with nextProps.someProp and prevState.cachedSomeProp
  return {
    cachedSomeProp: nextProps.someProp,
    // ... other derived state properties
  };
}
任何不影响状态的内容都可以放入
componentdiddupdate
,甚至还有一个
getSnapshotBeforeUpdate
用于非常低级的内容

更新:要了解新的(和旧的)生命周期方法,该软件包可能会有所帮助。

正如我们所说,在绝大多数情况下,您根本不需要
getDerivedStateFromProps

如果您只想计算某些派生数据,请执行以下任一操作:

  • 直接在
    渲染中执行该操作
  • 或者,如果重新计算成本很高,请使用像
    memoizeone
    这样的记忆辅助工具
  • 下面是最简单的“之后”示例:


    查看了解更多信息。

    如丹·阿布拉莫夫所述

    在渲染器内部执行此操作

    实际上,我们将这种方法与memoise one一起用于任何形式的代理道具到状态计算

    我们的代码看起来是这样的

    // ./decorators/memoized.js  
    import memoizeOne from 'memoize-one';
    
    export function memoized(target, key, descriptor) {
      descriptor.value = memoizeOne(descriptor.value);
      return descriptor;
    }
    
    // ./components/exampleComponent.js
    import React from 'react';
    import { memoized } from 'src/decorators';
    
    class ExampleComponent extends React.Component {
      buildValuesFromProps() {
        const {
          watchedProp1,
          watchedProp2,
          watchedProp3,
          watchedProp4,
          watchedProp5,
        } = this.props
        return {
          value1: buildValue1(watchedProp1, watchedProp2),
          value2: buildValue2(watchedProp1, watchedProp3, watchedProp5),
          value3: buildValue3(watchedProp3, watchedProp4, watchedProp5),
        }
      }
    
      @memoized
      buildValue1(watchedProp1, watchedProp2) {
        return ...;
      }
    
      @memoized
      buildValue2(watchedProp1, watchedProp3, watchedProp5) {
        return ...;
      }
    
      @memoized
      buildValue3(watchedProp3, watchedProp4, watchedProp5) {
        return ...;
      }
    
      render() {
        const {
          value1,
          value2,
          value3
        } = this.buildValuesFromProps();
    
        return (
          <div>
            <Component1 value={value1}>
            <Component2 value={value2}>
            <Component3 value={value3}>
          </div>
        );
      }
    }
    
    /./decorators/memonized.js
    从“memoize one”导入memoizeOne;
    已记忆的导出函数(目标、键、描述符){
    descriptor.value=memoizeOne(descriptor.value);
    返回描述符;
    }
    //./components/exampleComponent.js
    从“React”导入React;
    从'src/decorators'导入{memonized};
    类ExampleComponent扩展了React.Component{
    buildValuesFromProps(){
    常数{
    监视Prop1,
    监视Prop2,
    观看节目3,
    观看节目4,
    观看节目5,
    }=这是道具
    返回{
    值1:buildValue1(watchedProp1,watchedProp2),
    值2:buildValue2(watchedProp1、watchedProp3、watchedProp5),
    值3:构建值3(watchedProp3、watchedProp4、watchedProp5),
    }
    }
    @回忆
    构建值1(watchedProp1、watchedProp2){
    返回。。。;
    }
    @回忆
    构建值2(watchedProp1、watchedProp3、watchedProp5){
    返回。。。;
    }
    @回忆
    构建值3(watchedProp3、watchedProp4、watchedProp5){
    返回。。。;
    }
    render(){
    常数{
    价值1,
    价值2,
    价值3
    }=this.buildValuesFromProps();
    返回(
    );
    }
    }
    
    它的好处是,您不需要在
    getDerivedStateFromProps
    componentWillReceiveProps
    中编写大量的比较样板文件,并且可以跳过构造函数中的复制粘贴初始化

    注意:


    此方法仅用于将道具代理到状态,如果您有一些内部状态逻辑,它仍然需要在组件生命周期中处理。

    getDerivedStateFromProps用于在渲染前更新状态,并使用道具条件进行更新

    GetDerivedStateFromPropd在props value的帮助下更新stats值


    阅读。

    啊,我把问题搞糟了。实际上,我的意思是
    组件将接收道具
    我曾想过使用我的状态保存以前的道具,但我真的想避免实现它所需的额外代码和逻辑。我会调查你提到的其他一些事情。非常感谢!对于这种难以理解的React API更改,必须在一个状态中存储以前的道具只是一个样板工作区。对于许多开发人员来说,这看起来像是一个反模式和一个回归变化。不是批评你的Oblosys,而是反应团队。@AxeEffect这是因为
    getDerivedStateFromProps
    从来没有真正用于记忆。请看下面我的回答,我在那里描述了推荐的方法。这是打字错误吗?您是否错过了
    ?那就是我们应该返回整个状态对象,还是只返回我们关心的部分。如果在绝大多数情况下都不需要,那么我很惊讶这是一个如此迫切需要的更改,它将破坏数千个工作项目。看起来React团队从工程开始。从组件将接收Props更改为getDerivedStateFromProps。它不是破坏而是强制重构所有现有代码,这非常耗时。而且似乎没有什么好处,因为你说在绝大多数情况下你根本不应该使用它。为什么要为一些本来就不应该使用的东西修改API呢?我希望Dan Abramov能对此评论做出回应。@DanAbramov有没有关于为什么要进行这种修改的答案?事实上,在我们的项目中经常使用这种方法。当新数据出现时,在屏幕上显示如snackbar之类的内容,1个示例
    componentWillReceiveProps
    很简单,而且很有效。为什么要为了这个静态垃圾而删除它呢?标题应该是“如何在React团队竭尽全力反对它的情况下让事情运转起来”
    // ./decorators/memoized.js  
    import memoizeOne from 'memoize-one';
    
    export function memoized(target, key, descriptor) {
      descriptor.value = memoizeOne(descriptor.value);
      return descriptor;
    }
    
    // ./components/exampleComponent.js
    import React from 'react';
    import { memoized } from 'src/decorators';
    
    class ExampleComponent extends React.Component {
      buildValuesFromProps() {
        const {
          watchedProp1,
          watchedProp2,
          watchedProp3,
          watchedProp4,
          watchedProp5,
        } = this.props
        return {
          value1: buildValue1(watchedProp1, watchedProp2),
          value2: buildValue2(watchedProp1, watchedProp3, watchedProp5),
          value3: buildValue3(watchedProp3, watchedProp4, watchedProp5),
        }
      }
    
      @memoized
      buildValue1(watchedProp1, watchedProp2) {
        return ...;
      }
    
      @memoized
      buildValue2(watchedProp1, watchedProp3, watchedProp5) {
        return ...;
      }
    
      @memoized
      buildValue3(watchedProp3, watchedProp4, watchedProp5) {
        return ...;
      }
    
      render() {
        const {
          value1,
          value2,
          value3
        } = this.buildValuesFromProps();
    
        return (
          <div>
            <Component1 value={value1}>
            <Component2 value={value2}>
            <Component3 value={value3}>
          </div>
        );
      }
    }