首頁 > web前端 > js教程 > 關於React 實作專案的範例詳解 (三)

關於React 實作專案的範例詳解 (三)

黄舟
發布: 2017-07-24 15:58:28
原創
1455 人瀏覽過

React在Github上已經有接近70000的 star 數了,是目前最熱門的前端框架。而我學習React也有一段時間了,現在就開始用 React+Redux 來實戰吧!

上回說到使用Redux進行狀態管理,這次我們使用Redux-saga 管理Redux 應用非同步操作

React 實踐專案(一)

#React實作專案(二)

React 實作專案(三)

- 首先我們來看看登陸的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 監聽發起的action,然後決定基於這個action 來做什麼:是發起一個非同步呼叫(例如一個Ajax 請求),還是發起其他的action 到Store,甚至是呼叫其他的Sagas。

具體到這個登陸功能就是我們在登陸彈窗點擊登陸時會發出一個 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

<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;toolbar:false;">/** * Created by Yuicon on 2017/6/27. */ import {createStore, applyMiddleware } from &amp;#39;redux&amp;#39;; import createSagaMiddleware from &amp;#39;redux-saga&amp;#39; import reducer from &amp;#39;../reducer/reducer&amp;#39;; import rootSaga from &amp;#39;../sagas/sagas&amp;#39;; const sagaMiddleware = createSagaMiddleware(); const store = createStore( reducer, applyMiddleware(sagaMiddleware) ); sagaMiddleware.run(rootSaga); export default store;</pre><div class="contentsignin">登入後複製</div></div>Redux-saga 使用 Generator 函數實作

    #監聽action
  • 建立src/redux/sagas/sagas.js
/**
 * Created by Yuicon on 2017/6/28.
 */
import { takeLatest } from &#39;redux-saga/effects&#39;;
import {registerUserAsync, loginUserAsync} from &#39;./users&#39;;
import {REGISTER_USER, LOGIN_USER} from &#39;../action/users&#39;;

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: &#39;POST&#39;,
        headers: {
          &#39;Content-Type&#39;: &#39;application/json&#39;
        },
        body: JSON.stringify(user)
      }).then(response => response.json())
        .then(json => {
          return json;
        })
        .catch(ex => console.log(&#39;parsing failed&#39;, ex));
    };
    登入後複製

建立src/redux/sagas/users. js
  • /**
     * Created by Yuicon on 2017/6/30.
     */
    import {select, put, call} from &#39;redux-saga/effects&#39;;
    import {getAuth, getUsers} from &#39;./selectors&#39;;
    import {loginSuccessAction, loginFailureAction, registerSuccessAction, registerFailureAction} from &#39;../action/users&#39;;
    import {login, register} from &#39;./api&#39;;
    import &#39;whatwg-fetch&#39;;
    
    export function* loginUserAsync() {
      // 获取Store state 上的数据
      const auth = yield select(getAuth);
      const user = auth.get(&#39;user&#39;);
      // 发起 ajax 请求
      const json = yield call(login.bind(this, user), &#39;login&#39;);
      if (json.success) {
        localStorage.setItem(&#39;token&#39;, 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) 呼叫fn 函數並以args 為參數,如果結果是一個Promise,middleware 會暫停直到這個Promise 被resolve,resolve 後Generator會繼續執行。 或者直到 Promise 被 reject 了,如果是這種情況,將在 Generator 中拋出錯誤。
    Redux-saga 詳細api文檔

    結語
    • 我在工作時用的是Redux-Thunk,Redux- Thunk 相對來說更容易實現和維護。但對於複雜的操作,尤其是面對複雜非同步操作時,Redux-saga 更有優勢。到此我們完成了一個 Redux-saga 的入門教程,Redux-saga 還有很多奇妙的地方,

    以上是關於React 實作專案的範例詳解 (三)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板