Reactの「componentDidUpdate」メソッドをいつ使用するのですか?


108

私は何十ものReactファイルを書きました、決してcomponentDidUpdateメソッドを使用しません。

この方法を使用する必要がある典型的な例はありますか?

単純なデモではなく、実際の例をいくつか欲しい。

答えてくれてありがとう!



ロード時にコンポーネントの初期状態を設定したい場合の単純なケース。
Rajesh

@Rajeshそれを説明したり、例を挙げたりできますか?ありがとう!
slideshowp2

1
最も一般的なユースケースは、DOM上で直接動作する他のライブラリー(jQuery、D3 ...)があり、Reactと組み合わせている場合だと思います。このようなシナリオで、他のライブラリーがDOM変換を実行する必要がある場合は、componentDidUpdateを使用して、ReactのシャドウDOMが実際のDOMにフラッシュされていることを確認する必要があります。
ホルヘ

1
@Jorgeのコメントについて詳しく述べると、最も一般的なケースは、Reactが更新された後で実際のDOMから読み取ることです。たとえば、DOM要素の正確な寸法、またはビューポート内のDOM要素の位置を知りたい場合。たとえば、管理するために反応させたいアニメーションやトランジションの場合。反応がレンダリングされた後にDOMを変更するためにjQueryを使用することは絶対にお勧めしません。反応+別のライブラリが同じDOMを変更することは悪い考えです。
wintvelt 2016

回答:


88

簡単な例は、ユーザーから入力データを収集し、Ajaxを使用してそのデータをデータベースにアップロードするアプリです。以下は簡単な例です(実行していない-構文エラーがある可能性があります):

export default class Task extends React.Component {
  
  constructor(props, context) {
    super(props, context);
    this.state = {
      name: "",
      age: "",
      country: ""
    };
  }

  componentDidUpdate() {
    this._commitAutoSave();
  }

  _changeName = (e) => {
    this.setState({name: e.target.value});
  }

  _changeAge = (e) => {
    this.setState({age: e.target.value});
  }

  _changeCountry = (e) => {
    this.setState({country: e.target.value});
  }

  _commitAutoSave = () => {
    Ajax.postJSON('/someAPI/json/autosave', {
      name: this.state.name,
      age: this.state.age,
      country: this.state.country
    });
  }

  render() {
    let {name, age, country} = this.state;
    return (
      <form>
        <input type="text" value={name} onChange={this._changeName} />
        <input type="text" value={age} onChange={this._changeAge} />
        <input type="text" value={country} onChange={this._changeCountry} />
      </form>
    );
  }
}

したがって、コンポーネントにstate変更があるたびに、データが自動保存されます。それを実装する他の方法もあります。これcomponentDidUpdateは、DOMが更新され、更新キューが空になった後に操作を実行する必要がある場合に特に便利です。これはおそらく、複雑な上最も有用だrendersstateか、DOMの変更またはあなたがする何かを必要とするとき、絶対に実行される最後の事。

上記の例はかなり単純ですが、おそらくポイントを証明します。現在のところ、すべてのキーストロークで実行されるため、自動保存を実行できる回数を制限すること(たとえば、最大10秒ごと)を改善することができます。

このフィドルについてもデモを行い、デモを行いました。


詳細については、公式ドキュメントを参照してください。

componentDidUpdate()更新が発生した直後に呼び出されます。このメソッドは、最初のレンダリングでは呼び出されません。

これは、コンポーネントが更新されたときにDOMを操作する機会として使用します。現在の小道具を以前の小道具と比較している限り、これはネットワーク要求を行うのにも適しています(たとえば、小道具が変更されていない場合、ネットワーク要求は必要ない場合があります)。


私はthis.setState({...}, callback)callback等しい_commitAutoSaveと思いますか、あなたはどう思いますか?それで、このケースはcomponentDidUpdate方法を使用できると思いますが、そうである必要はありません、私は正しいのですか?フィドル
slideshowp2

1
はい、コールバックを使用できますが、連続して実行される複数のsetStateがある場合、またはその場合、問題はより複雑になります。
クリス

ご回答有難うございます。したがって、使用する1つのケースcomponentDidUpdateは、複数のsetStatesを解決することです!他のアイデアはありますか?
slideshowp2

@novaline私は彼らがreact-soundコンポーネントgithub.com/leoasis/react-sound/blob/master/src/index.jsでそれを使用しているのを目にしています..彼らがなぜそれを使用しているのか正確にはわかりませんが、私はあなたが見てみるためにリンクを共有します。
サラ、

3
これは良い例ですが、Reactのドキュメントには重要な推奨事項がありません。「現在の小道具を以前の小道具と比較している限り、これはネットワーク要求を行うのにも良い場所です(たとえば、小道具が変更されていない場合、ネットワーク要求は必要ないかもしれません)。」 reactjs.org/docs/react-component.html#componentdidupdate 同様に、setStateCDUで呼び出すときはいつでも、呼び出しを条件付きロジックでラップする必要があります。
theUtherSide

5

場合によっては、コンストラクターまたはcomponentDidMountの小道具から状態値を追加できます。小道具が変更されたが、コンポーネントが既にマウントされているため、componentDidMountが実行されず、コンストラクターも実行されない場合は、setStateを呼び出す必要があります。この特定のケースでは、propsが変更されたため、componentDidUpdateを使用できます。新しいpropsを使用して、componentDidUpdateでsetStateを呼び出すことができます。


2

componentDidUpdate()ハイチャートで使用しました。

このコンポーネントの簡単な例を次に示します。

import React, { PropTypes, Component } from 'react';
window.Highcharts = require('highcharts');

export default class Chartline extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      chart: ''
    };
  }

  public componentDidUpdate() {
    // console.log(this.props.candidate, 'this.props.candidate')
    if (this.props.category) {
      const category = this.props.category ? this.props.category : {};
      console.log('category', category);
      window.Highcharts.chart('jobcontainer_' + category._id, {
        title: {
          text: ''
        },
        plotOptions: {
          series: {
            cursor: 'pointer'
          }
        },
        chart: {
          defaultSeriesType: 'spline'
        },
        xAxis: {
          // categories: candidate.dateArr,
          categories: ['Day1', 'Day2', 'Day3', 'Day4', 'Day5', 'Day6', 'Day7'],
          showEmpty: true
        },
        labels: {
          style: {
            color: 'white',
            fontSize: '25px',
            fontFamily: 'SF UI Text'
          }
        },
        series: [
          {
            name: 'Low',
            color: '#9B260A',
            data: category.lowcount
          },
          {
            name: 'High',
            color: '#0E5AAB',
            data: category.highcount
          },
          {
            name: 'Average',
            color: '#12B499',
            data: category.averagecount
          }
        ]
      });
    }
  }
  public render() {
    const category = this.props.category ? this.props.category : {};
    console.log('render category', category);
    return <div id={'jobcontainer_' + category._id} style={{ maxWidth: '400px', height: '180px' }} />;
  }
}

2
componentDidUpdate(prevProps){ 

    if (this.state.authToken==null&&prevProps.authToken==null) {
      AccountKit.getCurrentAccessToken()
      .then(token => {
        if (token) {
          AccountKit.getCurrentAccount().then(account => {
            this.setState({
              authToken: token,
              loggedAccount: account
            });
          });
        } else {
          console.log("No user account logged");
        }
      })
      .catch(e => console.log("Failed to get current access token", e));

    }
}

1

このライフサイクルメソッドは、更新が発生するとすぐに呼び出されます。componentDidUpdate()メソッドの最も一般的な使用例は、propまたは状態の変更に応じてDOMを更新することです。

このライフサイクルでsetState()を呼び出すことができますが、前の状態からの状態または小道具の変化を確認するために、条件にラップする必要があることに注意してください。setState()を誤って使用すると、無限ループが発生する可能性があります。このライフサイクルメソッドの一般的な使用例を示す以下の例をご覧ください。

componentDidUpdate(prevProps) {
 //Typical usage, don't forget to compare the props
 if (this.props.userName !== prevProps.userName) {
   this.fetchData(this.props.userName);
 }
}

上記の例では、現在の小道具を以前の小道具と比較していることに注意してください。これは、小道具が現在のものから変更されているかどうかを確認するためのものです。この場合、小道具が変更されていない場合は、APIを呼び出す必要はありません。

詳細については、公式ドキュメントを参照してください


の場合はthis.fetchData is not a functionどうしますか?
tomrlh

tomrlh関数呼び出しです
Kashif

0

状態に変更があり、副作用を呼び出す必要がある場合(APIへのリクエスト-get、put、post、deleteなど)。すでに呼び出されているcomponentDidUpdate()ため、呼び出す必要がありますcomponentDidMount()

componentDidUpdate()で副作用を呼び出した後、の応答データに基づいて状態を新しい値に設定できますthen((response) => this.setState({newValue: "here"}))。状態を新しい値に設定すると、componentDidUpdate()が再び呼び出されるため、確認するprevPropsprevState、無限ループを回避する必要があることを確認してください。

ベストプラクティスのために副作用を呼び出す場所は2つあります-componentDidMount()とcomponentDidUpdate()

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.