web-dev-qa-db-ja.com

ComponentWillReceivePropsではなく、ライフサイクルメソッドgetDerivedStateFromPropsを使用する方法

新しいライフサイクルメソッドcomponentWillReceivePropsを採用するため、getDerivedStateFromPropsは今後のリリースで完全に廃止される予定です。

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

調べてみると、nextPropsの場合と同様に、this.propscomponentWillReceivePropsを直接比較することはできません。これを回避する方法はありますか?

また、オブジェクトを返すようになりました。戻り値が本質的に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)
      });
    }
  }
}

の後

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

componentWillReceivePropsの削除について:あなたはgetDerivedStateFromPropscomponentDidUpdateの組み合わせでその使用を扱うことができるはずです。 Reactブログ記事 例えばマイグレーションを見てください。そして、getDerivedStateFromPropsによって返されたオブジェクトは、setStateに渡されたオブジェクトと同様に状態を更新します。

あなたが本当にプロップの古い値を必要とするならば、あなたはいつでもこのような何かであなたの状態にそれをキャッシュすることができます:

state = { cachedSomeProp: null };

static getDerivedStateFromProps(nextProps, prevState) {
  // do things with nextProps.someProp and prevState.cachedSomeProp
  return {
    cachedSomeProp: nextProps.someProp,
    ..
  };
}

状態に影響を与えないものなら何でもcomponentDidUpdateに入れることができ、非常に低レベルのもの用のgetSnapshotBeforeUpdateさえあります。

更新:新しい(そして古い)ライフサイクルメソッドを理解するには、 react-lifecycle-visualizer パッケージが役に立つかもしれません。

59
Oblosys

私達最近Reactブログに投稿した _ほとんどの場合あなたは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);
    // ...
  }
}

詳しくはブログ記事のこのセクションをご覧ください。

29
Dan Abramov

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

その利点は、getDerivedStateFromPropscomponentWillReceivePropsの中に大量の比較ボイラープレートをコーディングする必要がなく、コンストラクタの中でコピーアンドペーストの初期化をスキップできることです。

注意:

この方法は、コンポーネントのライフサイクルで処理する必要がある内部ステートロジックがある場合に、プロップをステートにプロキシするためにのみ使用されます。

2
mpospelov