5

Redux を React プロジェクトに統合しようとしています。現在、私は Flux フレームワークを使用していません。

私のアプリは API からいくつかのデータを取得し、次のようにきれいな方法で表示します。

componentDidMount() {
  getData();
}

getData() {
  const self = this;

  ajax({
    url: apiUrl,
  })
  .success(function(data) {
    self.setState({
      data: data,
    });
  })
  .error(function() {
    throw new Error('Server response failed.');
  });
}

Redux について読んで、成功データをストアに保存する処理に使用できる 2 つのアプローチに落ち着きました。

  • 非同期ミドルウェアを使用する、または
  • ADD_DATAajax 関数の成功コールバックからアクションをディスパッチする

しかし、どちらがより良いアプローチかはわかりません。

コールバックでのアクションのディスパッチは、実装と理解が容易に思えますが、非同期ミドルウェアは、関数型言語の操作に慣れていない人には説明しにくいものです。

4

4 に答える 4

11

個人的には、これを実現するためにカスタム ミドルウェアを使用することを好みます。アクションを追跡するのが少し簡単になり、ボイラープレート IMO が少なくなります。

特定の署名に一致するアクションから返されたオブジェクトを探すようにミドルウェアをセットアップしました。このオブジェクト スキーマが見つかった場合は、特別に処理します。

たとえば、次のようなアクションを使用します。

export function fetchData() {
  return {
    types: [ FETCH_DATA, FETCH_DATA_SUCCESS, FETCH_DATA_FAILURE ],
    promise: api => api('foo/bar')
  }
}

私のカスタム ミドルウェアは、オブジェクトにtypes配列とpromise関数があることを認識し、それを特別に処理します。外観は次のとおりです。

import 'whatwg-fetch';

function isRequest({ promise }) {
  return promise && typeof promise === 'function';
}

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  } else {
    const error = new Error(response.statusText || response.status);
    error.response = response.json();
    throw error;
  }
}

function parseJSON(response) {
  return response.json();
}

function makeRequest(urlBase, { promise, types, ...rest }, next) {
  const [ REQUEST, SUCCESS, FAILURE ] = types;

  // Dispatch your request action so UI can showing loading indicator
  next({ ...rest, type: REQUEST });

  const api = (url, params = {}) => {
    // fetch by default doesn't include the same-origin header.  Add this by default.
    params.credentials = 'same-origin';
    params.method = params.method || 'get';
    params.headers = params.headers || {};
    params.headers['Content-Type'] = 'application/json';
    params.headers['Access-Control-Allow-Origin'] = '*';

    return fetch(urlBase + url, params)
      .then(checkStatus)
      .then(parseJSON)
      .then(data => {
        // Dispatch your success action
        next({ ...rest, payload: data, type: SUCCESS });
      })
      .catch(error => {
        // Dispatch your failure action
        next({ ...rest, error, type: FAILURE });
      });
  };

  // Because I'm using promise as a function, I create my own simple wrapper
  // around whatwg-fetch. Note in the action example above, I supply the url
  // and optionally the params and feed them directly into fetch.

  // The other benefit for this approach is that in my action above, I can do 
  // var result = action.promise(api => api('foo/bar'))
  // result.then(() => { /* something happened */ })
  // This allows me to be notified in my action when a result comes back.
  return promise(api);
}

// When setting up my apiMiddleware, I pass a base url for the service I am
// using. Then my actions can just pass the route and I append it to the path
export default function apiMiddleware(urlBase) {
  return function() {
    return next => action => isRequest(action) ? makeRequest(urlBase, action, next) : next(action);
  };
}

個人的には、このアプローチが気に入っています。多くのロジックを一元化し、API アクションの構造を標準的に適用できるからです。これの欠点は、redux に慣れていない人にとっては魔法のように感じるかもしれないということです。私はサンクミドルウェアも使用しており、これらの両方が一緒になって、これまでのすべてのニーズを解決しています。

于 2015-12-16T17:17:53.607 に答える
3

redux-thunk以下に示すように、ajax呼び出しを行いredux-promise、約束を処理するために使用します。

  function getData() {             // This is the thunk creator
    return function (dispatch) {   // thunk function
      dispatch(requestData());     // first set the state to 'requesting'
      return dispatch(
        receiveData(               // action creator that receives promise
          webapi.getData()         // makes ajax call and return promise
        )
      );
    };
  }

コールバックでアクションをディスパッチすることは、初めての人にとって理解しやすいように思えるかもしれませんが、ミドルウェアを使用することには次の利点があります。

  • サンクを使用すると、複数のアクションをディスパッチできます (上記の例のように -- 最初に状態を「リクエスト中」に設定します。これは、インジケーターの読み込みなどで使用できます)。
  • 条件付きで追加のアクションをディスパッチできます。たとえば、最後のフェッチからの時間がしきい値を超えた場合にのみフェッチする
  • これらすべてをミドルウェアなしで実装することもできますが、ミドルウェアを使用すると、すべての非同期動作をアクション クリエーター内に保持できます。
于 2015-12-16T05:39:26.977 に答える