title: 關于Redux為核心的應用開發簡介
date: 2017-04-20 08:05:04
categories: React-native
tags: Redux
問題出發點,當我們在UI組件中執行交互操作(點擊,滑動,提交),我們要考慮到怎么來響應操作.函數式編程里有個圖,有一個機器,從一邊放入肉,另一邊出火腿.這就是一個流程.application的操作其實就是解決
點擊=>結果展示
的流程.
但是實際流程中需要解決的問題很多.我們要考慮怎么來更好的管理application 的狀態問題. 具備javascript的基礎知識,幾個模式設計的東西,函數式編程的知識,React的知識,Redux的思想.可以說想在實際應用中玩轉React/Redux/Redux-saga/immutable。需要掌握的東西還是很多的.
我先寫一點具體的一些學習內容和需要的思想.
輔助觀念轉變的一個生活實例
先看個電燈電路

- 控制開關執行動作(操作),
- 電燈根據開關的動作來改變狀態,
- 電燈的狀態不是由自己決定的,電路里有電了就會亮,沒電了就不亮,像木偶一樣受到控制.
飛機座艙

各個儀表都和自己的傳感器連接在一起,加上冗余備份的儀表,很難設計和維護

80-90年代的window操作系統(不止windows奧),起源其實就是早期美國國防部的科研項目.
傳感器和顯示屏就沒有那么多線了.由數據總線來做集中統一處理.
理解React/Redux/Redux-saga架構的基礎知識
函數式編程思想

函數式編程把流程拆為幾個有聯系的步驟,可以分解流程,易于維護.合起來完成一個具體的任務.
但是這只是函數式編程的一個組成部分
在javascript的函數式編程中用到很多概念
- 函數作為一類對象,可以作為數組的元素,可以作為函數的參數來傳遞.
- 基于流的編程(
redux-saga就是基于流的編程
).
基于流的編程 -
閉包的概念
閉包的概念圖


- high-order function 接受其他函數作為參數的函數
- 純函數,對象的immutable,狀態改變.
一個實際的流程分析
在用戶提交表單的時候,我們想要做如下事情:
1.
校驗一些輸入信息 (簡單, 寫在組件里)
Validate方法,可以考慮導入redux-form組件,自帶驗證方法
2.
驗證以后可以讓提交按鈕改為可以提交狀態了
```
//login.UI.js登錄組件
this.props.dispatch(userLoginRequest(submit_info));
//已經結束了,不要想太多,用戶和組件的交互就是表單輸入和提交按鈕
//所以這里也執行這個過程就可以了.
```
3.
彈起提示信息(React組件化的優勢,公共組件)
```
//login.Ui.js
//Lodaing組件
this.props.isFetching?<Loading>:null
```
4.
提交后端服務 (我們用fetch,這個是不變的,redux只是對流程的控制,并不是要改變實際做事的方法)
5.
拿到后端返回狀態 (promise resolve)
6.
隱藏提示信息 (鴻門宴啊,摔杯為號,這不就是狀態嗎?)
```
//login.UI.js
this.props.isFetching?<Loading>:null
```
7.
更新redux store (reducer的操作)
//login.reducer.js
return state.merge(resolve.result);
8.
登錄界面的任務完成了.根據業務需要跳轉到對應的頁面
//reducer.js
return state.merge(resolve.result);
//login.js
this.props.loginsuccess?(Action.Mycenter):(Action.refresh)
這里我們就把登錄的流程做了分解.好處是很多的,流程都是根據狀態來的變化的,
代碼書寫清晰,在每一步的dubug和測試過程都很容易,因為我們可以獲取每一步的狀態
由于有redux-logger的中間件存在,我們還可以查看每一步的狀態變化.好像還有圖形化的界面來顯示state的變化.
總的原則是React組件只負責信息展示,簡單的驗證
復雜的邏輯現在全部在Redux中來實現
副作用(side effect)到底是個什么?
副作用其實就可以理解為由外部API提供的服務.這個服務和我們的app的流程是沒有關系的,我們只需要給接口提供參數,等待接口返回數據就可以了.
React/Redux/Redux-saga
React的概念,原理
-
React內心是虛擬DOM,在react中的html代碼實際是React渲染的模板
react組件中的html代碼叫jsx代碼,不是實際的html代碼,是js代碼 - React渲染動態內容的方式通過外部父組件傳入的props和組件內部的state來實現
絕對不可以搞錯的概念:組件之間要傳遞參數只能通過props來實現,state只能在組件內部使用,如果要把sate傳遞到其他組件,一定要經過轉換
在React中,props和state都有兩類不同的id來區分,不同的id類型是找不到對方的內容的.Redux的mapStateToProps方法就是把State的類型id轉為props的類型id.
由此可以得出什么結論呢?
其實Redux也是一個React的組件.

******切記,切記*******
3.Connect這個函數是非常重要的函數
組件要訂閱state的變化,能夠訂閱dispatch的方法都是通過connect函數來執行的.
Redux的出現

Redux負責把React的邏輯處理獨立出來處理
Redux的要點有:
- 一個應用只有一個state
- state是只讀的,這是immutable的概念.
- 修改state只能是用純函數來執行,dispatch(Action(params))
一旦React的應用中加入Redux的構架以后,所有Appliction的核心就由組件轉變到Redux中了.如果和傳統的web的 browser/server來類比,Redux就變成了服務器的角色,state就承擔了數據庫的角色.
組件之前的state的改變現在要重新思考了.

組件之間就最好再也不要做數據的傳遞,組件要執行渲染的sate統一從Redux的store中獲取
.
這一步思考方法的改變是極為重要的.
如果一個流程的過程非常的復雜,我們應該怎么來處理?
這一點其實有很多的解決辦法,但是Redux-saga基本算是非常優秀的解決辦法,嚴格貫徹了函數流式編程的思想,把一個復雜邏輯處理為一個數據流.
Redux-saga就是我們的救世主
redux-saga把我們上面的所有登錄的流程可以寫到一個工作流里面,香腸機器的組裝
//login.saga.js
import {loginReuest loginFetching,loginSuccess,loginError } from '../actions/login';
//請求登錄的數據流過程
export function* loginRequestFlow(submit_info) {
try {
yield put(loginFetching(isFetching:true))
const userInfoFromRemoteService = yield call(request,submit_info,'get');
yield put(loginSuccess(userInfoFromRemoteService));
const errorMessage = articleList.showapi_res_error;
if (errorMessage && errorMessage !== '') {
yield toastShort(errorMessage);
}
} catch (error) {
yield put(loginSuccess([]));
toastShort('網絡發生錯誤,請重試');
}
}
export function* watchuserLoginRequest(sumbit_info) {
while (true) {
const {
sumbit_info
} = yield take(types.loginRequest);
yield fork(loginRequestFlow, );
}
}
//login.action.js
export function userLoginRequest(sumbit_info){
return {
types.loginRequest,
sumbit_info
}
}

Redux會監視這個數據流的觸發

Redux saga 暴露了幾個方法,稱為 Effects,定義如下:
Fork
執行一個非阻塞操作。
Take
暫停并等待action到達。
Race
同步執行多個 effect,然后一旦有一個完成,取消其他 effect。
Call
調用一個函數,如果這個函數返回一個 promise ,那么它會阻塞 saga,直到promise成功被處理。
Put
觸發一個Action。
Select
啟動一個選擇函數,從 state 中獲取數據。
takeLatest
意味著我們將執行所有操作,然后返回最后一個(the latest one)調用的結果。如果我們觸發了多個時間,它只關注最后一個(the latest one)返回的結果。
takeEvery
會返回所有已出發的調用的結果。
Redux-saga并沒有改變Redux對于state的處理,只不過借用了es6/es7的方法對一個相關流程的changeState函數進行了包裝而已.
所以理解Redux-saga的工作原理,對于React和Redux工作原理理解是前提.