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

How to use lifecycle method getDerivedStateFromProps as opposed to componentWillReceiveProps

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

经检查,您现在似乎无法像在 componentWillReceiveProps 中那样直接比较 this.propsnextProps。有什么解决办法吗?

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

下面是我在网上找到的例子:State derived from 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;
  }
}

关于 componentWillReceiveProps 的删除:您应该能够结合使用 getDerivedStateFromPropscomponentDidUpdate 来处理它的使用,请参阅 the React blog post 以了解迁移示例。是的,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 非常 low-level 的东西。

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

因为我们recently posted on the React blog,在绝大多数情况下你根本不需要getDerivedStateFromProps.

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

  1. 就在里面做吧render
  2. 或者,如果重新计算它很昂贵,请使用像 memoize-one 这样的记忆助手。

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

import memoize from "memoize-one";

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

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

查看 this section of the blog post 了解更多信息。

如 Dan Abramov 所述

Do it right inside render

我们实际上将这种方法与 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>
    );
  }
}

它的好处是您不需要在 getDerivedStateFromPropscomponentWillReceiveProps 中编写大量比较样板代码,并且您可以跳过构造函数中的复制粘贴初始化。

注意:

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

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

更新状态

GetDerivedStateFromPropd 借助道具值更新统计值

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