web-dev-qa-db-ja.com

componentDidMountに対するアクションをディスパッチします(react / redux)

私はリアクション/リデュースに新しい相対性理論です。そこで(おそらく哲学的な)質問をしたいのです。

反応コンポーネントのcomponentDidMountでアクションをディスパッチ(たとえば、api呼び出しをトリガー)してもかまいませんか?

そうでない場合、なぜどこでアクションをディスパッチする必要がありますか?

はいの場合、それ以上の質問はありませんか? :)

20
dritan

はい、componentDidMount()に対するアクションのディスパッチは問題ありません。最初のUIレンダリングが遅くなることはないので、推奨されることでもあります。

関数はコンポーネントが最初にレンダリングされた後に実行されるため、コンポーネントがレンダリングされてからAPI呼び出しからデータを受け取るまでの間に時間がかかる場合があることに注意してください。

10
Sammy I.

はい、必ずcomponentDidMountフックを使用する必要があります。

典型的なユースケースは次のとおりです。

  • コンポーネントが画面に表示されます(例:テーブル)
  • データを取得するためにサーバーへのリクエストがトリガーされます
  • コンポーネントをカバーするスピナー/ローダーが表示されます
  • データが戻ってくる
  • スピナーが削除され、データが表に表示されます。

私はそれが少し長いことを知っていますが、私はしばらくの間このタイプの問題に取り組んでいたので、私は次のパターンを共有すると思いました;)

コンポーネントがマウントされると、データの取得アクションがトリガーされます。アプリケーション状態の「isFetching」値は、スピナーが表示されるかどうかを決定します(私は「advanced-loader」またはそのようなライブラリを使用したと思います)

export default class MyComponent extends React.Component {

  componentDidMount() {
    AppDispatcher.dispatch({
      type: ActionTypes.FETCH_DATA,
    });
  }

  render() {
    let isFetching = this.props.my.application.path.isFetching;
    return (
      <Loader show={isFetching} message={'loading'}>
        <div>
          My Component
        </div>
      </Loader>
    );
  }
}

次に、ストアでFETCH_DATAがリクエストをトリガーします。

class AppStore extends ReduceStore {

  //......

  reduce(state, action) {

    let imState = Immutable.fromJS(state);

    switch (action.type) {

      //......

      case ActionTypes.FETCH_DATA:
        doGetRequest('/url_to_service');
        break;

      //......
    }
    return imState.toJS();
  }
}

リクエストは次のようになります。

function doGetRequest(endpoint, params = {}) {

  //request is some kind of AJAX library. In my case 'superagent'
  request.get(endpoint)
    .set('Accept','application/json')
    .query(params)
    .end(
      (err, res) => {
        if (res && res.ok) {
          receiveData(endpoint, "SUCCESS", res);
        } else {
          receiveData(endpoint, "FAIL");
    }});
}

完了すると、別のアクションをディスパッチします。

function receiveData(endpoint, state, responseData) {
  AppDispatcher.dispatch(
    {
      type: ActionTypes.SERVER_RESPONSE,
      endpoint: endpoint,
      state: state,
      payload: responseData
    }
  );
}

ストアに戻ると、2番目のアクションがキャッチされ、isFetchingフラグがfalseに設定されてから、アプリケーションデータが処理されます。

  reduce(state, action) {

    let imState = Immutable.fromJS(state);

    switch (action.type) {

      //......


      case ActionTypes.SERVER_RESPONSE: {

        imState = imState.setIn(['my','application','path', 'isFetching'], false)

        if (action.state == "SUCCESS") {
            //do something with the action.response data (via state update)
        }else if (action.state == "FAIL") {
            //maybe show an error message (via state update)
        }
        break;
      }
    }
    return imState.toJS();
  }
}

....この典型的なユースケースでは2つの「アクション」を使用します。最初のアクションはcomponentDidMountメソッドからトリガーされ、2番目のアクションはリクエストの完了後にトリガーされます。

このパターンが役立つことを願っています:)

4
Oliver Watkins

公式のReactのドキュメントによると、componentDidMountはそうするのにぴったりの場所です。

componentDidMount()は、コンポーネントがマウントされた直後に呼び出されます。 DOMノードを必要とする初期化はここに行く必要があります。 リモートエンドポイントからデータをロードする必要がある場合、これはネットワークリクエストをインスタンス化するのに適した場所です。

公式React componentDidMount()のドキュメント

1
Vivek Maharajh

ルートを使用する場合、アクションをディスパッチする別の推奨方法は、routes-method "onEnter"です。これは、コンポーネントがアクション(またはAPI呼び出し)に依存しないようにするためです。

私は個人的には両方の方法(componentDidMountとonEnter)は大丈夫だと思います。アプリケーションに最適なソリューションを選択するのはプログラマに任されています。

0
dritan