11
12

More than 5 years have passed since last update.

React.js × Fluxで非同期処理を行う場合の初期化とデータ挿入

Last updated at Posted at 2015-06-20

ReactをFluxで使う際、外部APIをキックしてデータを取得する非同期処理をどこに持たせるか。
ここの情報がドキュメントによって様々な為、悩んだ結果、以下のようにしました。

環境

React.js: 0.13.3

要望

  • Storeに非同期処理を持たせたくない
    (Store自身が非同期にデータを取得する処理を行う、というのをやめたい)
  • API -> Action ではなく、 Action -> API にしたい
    (非同期データの取得を待ち合わせ、Actionをコールしてデータを渡す、というのをやめたい)

実装

かなり簡略化してます。

app.jsx
import React from "react/addons"
import App from "./App";

// エンドポイントはまずコンポーネントの描画
React.render(<App id={<何らかの値>}/>, document.getElementById("app"));
App.jsx
// ~~ import処理 ~~

getState () {
  return {
    data: Store.getData()
  };
}

export default class App extends React.component {
  constructor () {
    this.state = getState();
  }

  componentWillMount () {
    // データ初期化処理をコール
    Action.init(this.props.id);
  }

  // ~~ Storeへのlisten ~~  

  _onChange () {
    this.setState(getState());
  }

  render () {
    // データ初期化前はfalseを返してリターン
    if (!this.state.data) {
      return false;
    }

    // ~~ render処理 ~~
  }
}
Action.jsx
// ~~ import処理 ~~

export default class Action {
  // アクションのメソッドがAPIをコールする
  init (id) {
    API.get(id)
    .done(data => {
      // データの取得が終わったらStoreに通知
      Dispatcher.dispatch({
        type: Constants.INIT,
        data: data
      });
    });
  }
}
Store.jsx
// ~~ import処理 ~~

var _data = null;
var Store = assign({}, EventEmitter.prototype, {
  getData () {
    return _data;
  },

  // ~~ emit、listener ~~
});

Dispatcher.register(action => {
  switch (action.type) {
    case Constants.INIT:
      _data = action.data;
      break;
  }
});

export default Store;

最初にコンポーネントをレンダリングし、コンポーネント内でデータの有無を判定してActionをコールしています。
componentWillMountはサーバサイドでは動作しないため、クライアントサイド実装に限られますが…)

もっと良いやり方がある気がしますが、一応これで要望を満たす実装はできました。

11
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
12