ホームページ  >  記事  >  ウェブフロントエンド  >  React実践プロジェクト事例を詳しく解説(3)

React実践プロジェクト事例を詳しく解説(3)

黄舟
黄舟オリジナル
2017-07-24 15:58:281421ブラウズ

React は Github 上に 70,000 近くのスターを持ち、現在最も人気のあるフロントエンド フレームワークです。しばらく React を学習していましたが、今では実際に React+Redux を使用し始めています。

前回はReduxを使った状態管理についてお話しました

React実践プロジェクト(1)

React実践プロジェクト(2)

今回はRedux-sagaを使ってReduxアプリケーションの非同期操作を管理します。 3)

- まず、ログインした Reducer

export const auth = (state = initialState, action = {}) => {
  switch (action.type) {
    case LOGIN_USER:
      return state.merge({
        'user': action.data,
        'error': null,
        'token': null,
      });
    case LOGIN_USER_SUCCESS:
      return state.merge({
        'token': action.data,
        'error': null
      });
    case LOGIN_USER_FAILURE:
      return state.merge({
        'token': null,
        'error': action.data
      });
    default:
      return state
  }
};

Sagas を見て、開始されたアクションを監視し、このアクションに基づいて何をすべきかを決定しましょう: 非同期呼び出し (Ajax など) を開始するかどうかリクエスト)、ストアに対して他のアクションを開始するか、他のサガを呼び出すことさえあります。

具体的なログイン機能は、ログイン ポップアップ ウィンドウをクリックすると、LOGIN_USER アクションが発行され、Sagas は LOGIN_USER アクションを監視し、Ajax リクエストを開始します。その結果、LOGIN_USER_SUCCESSアクションまたはLOGIN_USER_FAILUREアクションを開始することが決定されましたLOGIN_USER action,Sagas 监听到 LOGIN_USER action,发起一个 Ajax 请求到后台,根据结果决定发起 LOGIN_USER_SUCCESSaction 还是LOGIN_USER_FAILUREaction

接下来,我们来实现这个流程

  • 创建 Saga middleware 连接至 Redux store

在 package.json 中添加 redux-saga 依赖

"redux-saga": "^0.15.4"

修改 src/redux/store/store.js

/**
 * Created by Yuicon on 2017/6/27.
 */
import {createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga'
import reducer from '../reducer/reducer';

import rootSaga from '../sagas/sagas';

const sagaMiddleware = createSagaMiddleware();

const store = createStore(
  reducer,
  applyMiddleware(sagaMiddleware)
);

sagaMiddleware.run(rootSaga);

export default store;

Redux-saga 使用 Generator 函数实现

  • 监听 action

创建 src/redux/sagas/sagas.js

/**
 * Created by Yuicon on 2017/6/28.
 */
import { takeLatest } from 'redux-saga/effects';
import {registerUserAsync, loginUserAsync} from './users';
import {REGISTER_USER, LOGIN_USER} from '../action/users';

export default function* rootSaga() {
  yield [
    takeLatest(REGISTER_USER, registerUserAsync),
    takeLatest(LOGIN_USER, loginUserAsync)
  ];
}

我们可以看到在 rootSaga 中监听了两个 action 登陆和注册 。

在上面的例子中,takeLatest 只允许执行一个 loginUserAsync 任务。并且这个任务是最后被启动的那个。 如果之前已经有一个任务在执行,那之前的这个任务会自动被取消。

如果我们允许多个 loginUserAsync 实例同时启动。在某个特定时刻,我们可以启动一个新 loginUserAsync 任务, 尽管之前还有一个或多个 loginUserAsync 尚未结束。我们可以使用 takeEvery 辅助函数。

  • 发起一个 Ajax 请求

  • 获取 Store state 上的数据

selectors.js

/**
 * Created by Yuicon on 2017/6/28.
 */
export const getAuth = state => state.auth;
  • api

api.js

/**
 * Created by Yuicon on 2017/7/4.
 * 
 */

/**
 * 这是我自己的后台服务器,用 Java 实现
 * 项目地址:
 * 文档:http://139.224.135.86:8080/swagger-ui.html#/
 */
const getURL = (url) => `http://139.224.135.86:8080/${url}`;

export const login = (user) => {
  return fetch(getURL("auth/login"), {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(user)
  }).then(response => response.json())
    .then(json => {
      return json;
    })
    .catch(ex => console.log('parsing failed', ex));
};
  • 创建 src/redux/sagas/users.js

/**
 * Created by Yuicon on 2017/6/30.
 */
import {select, put, call} from 'redux-saga/effects';
import {getAuth, getUsers} from './selectors';
import {loginSuccessAction, loginFailureAction, registerSuccessAction, registerFailureAction} from '../action/users';
import {login, register} from './api';
import 'whatwg-fetch';

export function* loginUserAsync() {
  // 获取Store state 上的数据
  const auth = yield select(getAuth);
  const user = auth.get('user');
  // 发起 ajax 请求
  const json = yield call(login.bind(this, user), 'login');
  if (json.success) {
    localStorage.setItem('token', json.data);
    // 发起 loginSuccessAction
    yield put(loginSuccessAction(json.data));
  } else {
    // 发起 loginFailureAction
    yield put(loginFailureAction(json.error));
  }
}

select(selector, ...args) 用于获取Store state 上的数据
put(action) 发起一个 action 到 Store
call(fn, ...args)

次に、このプロセスを実装しましょう

  • パッケージ内の Redux ストア

に接続します。 redux-saga 依存関係を json


"redux-saga": "^0.15.4" に追加します

src/redux/store/store.js を変更します🎜rrreee🎜Redux-saga は Generator 関数を使用して🎜🎜🎜🎜リスニングアクションを実装します🎜🎜🎜🎜 src/redux/sagas/sagas.js🎜を作成しますrrreee🎜 rootSaga では、ログインと登録という 2 つのアクションが監視されていることがわかります。 🎜🎜上記の例では、takelatest は 1 つの loginUserAsync タスクの実行のみを許可します。そして、このタスクは最後に開始されるタスクです。 すでに実行中のタスクがある場合、前のタスクは自動的にキャンセルされます。 🎜🎜複数のloginUserAsyncインスタンスの同時起動を許可する場合。特定の時点で、以前の 1 つ以上の loginUserAsync タスクがまだ完了していなくても、新しい loginUserAsync タスクを開始できます。 takeEvery ヘルパー関数を使用できます。 🎜🎜🎜🎜Ajaxリクエストを開始する🎜🎜🎜🎜ストア状態のデータを取得する🎜🎜🎜🎜selectors.js🎜rrreee🎜🎜🎜api🎜🎜🎜🎜api.js🎜rrreee🎜 🎜🎜src/redux/sagas/を作成するusers.js🎜🎜🎜rrreee🎜select(selector, ...args) は、Store 状態のデータを取得するために使用されます🎜put(action) は、次のアクションを開始しますStore🎜 call(fn, ...args) は、args をパラメータとして fn 関数を呼び出します。結果が Promise の場合、ミドルウェアは Promise が解決されるまで一時停止します。実行を継続します。 または、Promise が拒否されるまで、その場合はジェネレーターでエラーがスローされます。 🎜🎜Redux-saga の詳細な API ドキュメント🎜🎜🎜🎜結論🎜🎜🎜🎜私は仕事で Redux-Thunk を使用していますが、Redux-Thunk は実装と保守が比較的簡単です。しかし、複雑な操作、特に複雑な非同期操作に直面した場合、Redux の話にはさらに利点があります。この時点で、Redux saga の入門チュートリアルは完了しました。Redux saga にはまだ素晴らしい点がたくさんあります 🎜🎜🎜。

以上がReact実践プロジェクト事例を詳しく解説(3)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。