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

And*_*rew 125 javascript lifecycle reactjs

它似乎componentWillReceiveProps将在即将发布的版本中完全淘汰,支持新的生命周期方法getDerivedStateFromProps.

https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

经过检查,看起来你现在无法在this.propsnextProps你之间进行直接比较componentWillReceiveProps.有没有办法解决?

此外,它现在返回一个对象.我是否正确地假设返回值基本上是this.setState

以下是我在网上找到的一个例子 https://github.com/reactjs/rfcs/blob/master/text/0006-static-lifecycle-methods.md#state-derived-from-propsstate

之前

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

  componentWillReceiveProps(nextProps) {
    if (this.props.someValue !== nextProps.someValue) {
      this.setState({
        derivedData: computeDerivedState(nextProps)
      });
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

Obl*_*sys 84

有关删除的componentWillReceiveProps:你应该能够与组合来处理它的用途getDerivedStateFromPropscomponentDidUpdate,看到的阵营博客文章,例如迁移.是的,通过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
  };
}
Run Code Online (Sandbox Code Playgroud)

任何不影响状态的东西都可以放入componentDidUpdate,甚至还有getSnapshotBeforeUpdate一些非常低级的东西.

更新:为了了解新的(和旧的)生命周期方法,react-lifecycle-visualizer包可能会有所帮助.

  • 必须在状态中存储先前的道具只是这种难以理解的React API更改的样板变通办法。在许多开发人员看来,这看起来像是反模式和回归更改。不是批评您Oblosys,而是React团队。 (3认同)
  • 我曾想过使用我的状态来保存以前的道具,但我真的想避免实现它所需的额外代码和逻辑.我会研究你提出的其他一些事情.非常感谢! (2认同)
  • @AxeEffect 这是因为 **`getDerivedStateFromProps` 从未真正用于记忆**。请参阅下面我描述的**推荐方法**的答案。 (2认同)

Dan*_*mov 43

正如我们最近发布的博客作出反应,在绝大多数情况下,你并不需要getDerivedStateFromProps在所有.

如果您只想计算一些派生数据,请:

  1. 在里面做吧 render
  2. 或者,如果重新计算它很昂贵,请使用memoization helper memoize-one.

这是最简单的"后"示例:

import memoize from "memoize-one";

class ExampleComponent extends React.Component {
  getDerivedData = memoize(computeDerivedState);

  render() {
    const derivedData = this.getDerivedData(this.props.someValue);
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

查看博客文章的这一部分以了解更多信息.

  • 如果在_vast_大多数情况下都不需要它,那么我很惊讶这是一个非常需要的改变,这个改变将打破成千上万的工作项目.看起来React团队开始进行工程设计. (38认同)
  • 从componentWillReceiveProps更改为getDerivedStateFromProps.它并没有破坏,而是强制重构所有现有代码,这非常耗时.并且似乎没什么好处,因为你说在绝大多数情况下你根本不应该使用它.为什么要为那些本来不应该使用的东西改变API的麻烦. (32认同)
  • @DanAbramov关于为什么会发生这种变化的任何答案? (5认同)
  • 我希望Dan Abramov对这一评论做出回应。 (3认同)
  • 实际上,在我们的项目中,这已被大量使用。为了在新数据出现时在屏幕上显示诸如Snackbars之类的内容,请参见示例1。componentWillReceiveProps很简单并且有效。为什么要删除此静态垃圾... (2认同)

mpo*_*lov 5

正如丹·阿布拉莫夫(Dan Abramov)所述

在渲染内部执行

实际上,我们将这种方法与备忘录一起用于任何用于状态计算的代理道具。

我们的代码看起来像这样

// ./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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

它的好处是,你不需要代码吨比较样板里面的getDerivedStateFromProps或者componentWillReceiveProps你可以跳过复制粘贴初始化一个构造函数中。

注意:

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