redux非同期操作実践について詳しく説明する。

5694 ワード

一、レdux基礎
redux
  • dispatch->中間件->reducer処理データ->変更store->subscribeを使用して、新しいビューを傍受storeに変更する方式で管理状態
  • は、すべての状態を一つのstoreオブジェクトに格納する
  • reducerは純関数であり、非同期動作は結果の不確実性から副作用を含むので、特別な処理が必要である

  • react-redux
  • コンテナコンポーネントは、データとトラフィックロジックの管理を担当し、UIのレンダリングを担当していない
  • UIコンポーネントは、UIレンダリングを提供し、状態がない、すなわち、this.stateを使用しない、状態はすべてthis.propsによって
  • を提供する。
  • はconnectによってコンテナコンポーネントを生成し、storeが変わるたびにconnectを呼び出し、connectは2つのパラメータを受信する。
  • mapStateToPropsは、UIコンポーネントのprops
  • に状態をマッピングする。
  • mapDisplatToPropsは、dispatch方法をUIコンポーネントのprops
  • にマッピングする。
  • Providerコンポーネントは、content APIを使用して、storeをトップから各階層のcomponentに転送し、connectのために
  • を使用する。
    二、レduxは非同期の中間部品を処理する。
    redux-thunk
  • redux-thunk中間部品許容actionは、方法
  • である。
  • ミドルウェアはactionを受信するとaction方法を実行し、結果をreducer
  • に提供する。
  • actionの混乱によるメンテナンスが困難になりました。
    redux-saga
  • sagaはactionを監督し、このactionに基づいてEffects動作を実行します。
  • Effectsは、ブロック、非ブロッキングコール、キャンセル、待ち時間、raceなどの動作
  • を含むフレキシブルなAPIを提供する。
  • は、隔離して非同期動作を実行しやすく、
  • をテストしやすい。
    三、redux-request-async-middleware
    先にreduxドキュメントの非同期actionから話してください。各インターフェースの呼び出しにはdispatchの3つの同期actionが必要です。それぞれ:
  • は、reducer要求の開始を通知するactionである。このようなactionに対して、reducerはstateの中のisFetchingマークを切り替えるかもしれません。これにより、UIにロードインターフェースを表示するように教える。
  • は、reducer要求の成功を通知するactionである。このようなactionの場合、reducerは、受信した新しいデータをstateに統合し、isFetchingをリセットすることができる。UIは、ロードインターフェースを隠し、受信したデータを表示します。
  • は、reducer要求の失敗を通知するactionである。このようなactionに対して、reducerはisFetchingをリセットするかもしれない。また、一部のreducerはこれらの失敗情報を保存し、UIに表示する。
  • つまりインターフェースの発起はこのようなものです。
    
    dispatch(fetchPostsRequest(subject));
    fetch(url).then(res => {
      dispatch(fetchPostsSuccess(subject, res));
    }).catch(e => {
      dispatch(fetchPostsFailure(subject, e));
    })
    
    私がやっていることは、この操作を中間部品にパッケージ化するだけで、特殊なところは:
  • のすべての非同期要求は、この3つのaction
  • を共有する。
  • は、どの要求が
  • であるかをsubjectで区別する。
  • はすべての結果をstore.requestsに入れます。
  • 中間のソースコード
    
    export const reduxRequest = store => next => action => {
      let result = next(action);
      let { type, subject, model } = action;
      let _next = action.next;
      if(type === FETCH_POSTS_REQUEST) {
        model().then(response => {
          _next && _next(response);
          store.dispatch(fetchPostsSuccess(subject, response));
        }).catch(error => {
          console.error(error);
          store.dispatch(fetchPostsFailure(subject, error));
        });
      }
      return result
    };
    
  • はredux-thunkと同じで、方法をactionに入れます。
  • 中間部品ブロッキングFETCH_POSTS_REQUEST actionは、非同期処理
  • を行う。
    ソースコード
    
    export const requests = (state = {}, action) => {
      switch (action.type) {
        case FETCH_POSTS_REQUEST:
          return assign({},
            state,
            {
              [action.subject]: {
                isFetching: true,
                state: 'loading',
                subject: action.subject,
                response: null,
                error: null,
              }
            }
          );
        case FETCH_POSTS_FAILURE:
          return assign({},
            state,
            {
              [action.subject]: {
                isFetching: false,
                state: 'error',
                subject: action.subject,
                response: state[action.subject].response,
                error: action.error,
              }
            }
          );
        case FETCH_POSTS_SUCCESS:
          return assign({},
            state,
            {
              [action.subject]: {
                isFetching: false,
                state: 'success',
                subject: action.subject,
                response: action.response,
              }
            }
          );
        case FETCH_POSTS_CLEAR:
          return assign({},
            state,
            {
              [action.subject]: {
                isFetching: false,
                state: 'cleared',
                subject: null,
                response: null,
                error: null,
              }
            }
          );
        default:
          return state;
      }
    }
    
  • は、結果をこのsubject対応下のレスポンスに入れ、エラーが発生したらエラーコードをerrorに入れます。
  • isFetchは、現在の要求状態
  • を表しています。
  • はまた、現在のステータスstateとsubject情報
  • を追加しました。
    要求をパッケージ化する
    
    const request = (subject, model, next) => {
      _dispatch(fetchPostsRequest(subject, model, next));
      return true;
    };
    
  • FETCH_を開始する方法を書く。POSTS_REQUEST action
  • つまり、要求を書く時にactionを管理しなくてもいいです。request方法
  • を直接呼び出します。
    結果をパッケージ化する
    
    const getResponse = state =>
      state
      && state.response !== null
      && state.response;
    
    const getLoading = (states = []) =>
      states.reduce((pre, cur) =>
        pre || (cur && cur.isFetching)
        , false)
      || false;
    
    
  • は、結果と複数の要求の下でloadingの状態を取得することができる
  • には、より多くの操作またはフォーマットがあり、また、リスト
  • などのパッケージ化を継続することができる。
    使用方法redux-request-async-middleware
    四、まとめ
  • は、reduxを使用して状態管理を行い、レduxの複雑な論理セットを作成する必要はなく、非同期動作の複雑さを最大程度低減する
  • を使用している。
  • は、フロントエンドがインターフェースを介してデータを処理し、記憶する項目
  • に適用される。
  • インターフェースはreduxによって処理され、ビューコンポーネントは内部stateによって処理され、外部は簡単なインターフェースだけを露出して動作し、トラフィック層と視層
  • を分離する。
  • は、react 16.3 new content APIを比較し、reduxの利点は、ホットキャストのミドルウェアと純関数reducerの書き方
  • にある。
    以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。