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

IT技术 javascript reactjs lifecycle
2021-04-06 16:00:14

看起来componentWillReceiveProps将在即将发布的版本中完全淘汰,取而代之的是一种新的生命周期方法getDerivedStateFromProps静态 getDerivedStateFromProps()

经过检查,您现在似乎无法在this.props之间进行直接比较nextProps,就像在 中一样componentWillReceiveProps有没有办法解决?

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

下面是我在网上找到的一个例子:State衍生自 props/state

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;
  }
}
4个回答

有关删除的componentWillReceiveProps:你应该能够与组合来处理它的用途getDerivedStateFromPropscomponentDidUpdate,看到的阵营博客文章,例如迁移。是的,由 返回的对象getDerivedStateFromProps更新状态类似于传递给 的对象setState

如果你真的需要一个 prop 的旧值,你总是可以用这样的东西将它缓存在你的状态中:

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
  };
}

任何不影响状态的东西都可以放进去componentDidUpdate,甚至还有一个getSnapshotBeforeUpdate用于非常低级的东西。

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

呃,我把问题搞砸了。我的意思是componentWillReceiveProps
2021-05-23 16:00:14
对于这种难以理解的 React API 更改,必须将先前的 prop 存储在状态中只是一个样板解决方法。对于许多开发人员来说,这看起来像是一种反模式和回归变化。不是批评你 Oblosys,而是 React 团队。
2021-05-27 16:00:14
@AxeEffect 这是因为getDerivedStateFromProps从来没有真正用于记忆请参阅我在下面描述推荐方法的答案
2021-06-04 16:00:14
我曾想过使用我的 state 来保存以前的 props,但我真的想避免实现它所需的额外代码和逻辑。我会调查你提出的其他一些事情。非常感谢!
2021-06-16 16:00:14
这是一个错字吗?你错过了...吗?那就是我们应该返回整个状态对象还是只返回我们关心的部分。
2021-06-19 16:00:14

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

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

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

这是最简单的“之后”示例:

import memoize from "memoize-one";

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

  render() {
    const derivedData = this.getDerivedData(this.props.someValue);
    // ...
  }
}

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

我很想对丹·阿布拉莫夫的评论做出回应。
2021-05-23 16:00:14
@DanAbramov 关于为什么会发生这种变化的任何答案?
2021-05-26 16:00:14
从 componentWillReceiveProps 更改为 getDerivedStateFromProps。这不是破坏而是强制重构所有现有代码,这非常耗时。并且似乎没有什么好处,因为您说在绝大多数情况下根本不应该使用它。为什么要为甚至不应该首先使用的东西更改 API 的麻烦。
2021-06-12 16:00:14
实际上在我们的项目中,这被大量使用。为了在新数据出现时在屏幕上显示 Snackbars 之类的东西,1 个示例。componentWillReceiveProps很简单,而且有效。为什么要为这个静态垃圾删除它......
2021-06-14 16:00:14
如果在绝大多数情况下不需要它,那么我很惊讶这是一个非常需要的更改,它将破坏数千个工作项目。看起来 React 团队是从工程开始的。
2021-06-17 16:00:14

正如丹·阿布拉莫夫所说

就在渲染里面做

我们实际上将这种方法与 memoise one 一起用于任何类型的代理props以进行状态计算。

我们的代码看起来像这样

// ./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>
    );
  }
}

它的好处是您不需要在内部编写大量比较样板,getDerivedStateFromProps或者componentWillReceiveProps您可以跳过构造函数内部的复制粘贴初始化。

笔记:

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

getDerivedStateFromProps用于在渲染之前更新状态并使用 props 条件更新

GetDerivedStateFromPropd 在 props 值的帮助下更新统计值

阅读https://www.w3schools.com/REACT/react_lifecycle.asp#:~:text=Lifecycle%20of%20Components,Mounting%2C%20Updating%2C%20and%20Unmounting