寫這篇筆記更正以前理解的誤區,背景呢,一次需求中實現根據參數 itemId 等分頁信息拉取接口至少5次, 並在state 中並保存合併對應itemId下的數據, 這裏有兩個步驟1,每次請求的數據在賦值給state以前 ,要獲取到原有state中的值; 2,合併操做。那如何在reduce 中獲取到原有state的值呢, 就是狀態管理了.react
redux 自己很是簡單,它只有三個核心概念:state、action 和 reducer, 直接看官網就能夠了, 或者網上成堆的10 分鐘理解 Redux。 將須要修改的 state 都存入到 store 裏, 發起一個 action 用來描述發生了什麼,用 reducers 描述 action 如何改變 state tree 。所以只有 reducer 能修改 state。redux 經過這些約束,讓數據的變化變得可預測、可回溯。在建立 store 的時候須要傳入 reducer,真正能改變 store 中數據的是 store.dispatch API。能夠採用兩種中間件redux-thunk 和redux-saga。 固然也能夠直接使用ant design pro是基於UmiJS、dva,而 dva 也是基於 redux、redux-saga 和 react-router 的進一步封裝。git
redux-thunk 中間件能夠容許你寫的 action creator 函數能夠返回 action 對象的同時,也能夠返回一個函數。函數傳遞兩個參數 (dispatch,getState), 在函數體內進行業務邏輯的封裝, getState() 方法獲取 state
這個中間件能夠被用來延緩分發 action 的時機,或者實現只在知足某個條件的時候才觸發 action。簡而言之,中間件都是對 store.dispatch () 的加強。如下是官網的一個例子github
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
const store = createStore(
reducers,
applyMiddleware(thunk)
);
// 並且可使用 Promise 來控制數據流。
function makeSandwichesForEverybody() {
return function (dispatch, getState) {
if (!getState().sandwiches.isShopOpen) {
// 返回 Promise 並非必須的,但這是一個很好的約定,
// 爲了讓調用者可以在異步的 dispatch 結果上直接調用 .then() 方法。
return Promise.resolve()
}
// 能夠 dispatch 普通 action 對象和其它 thunk,
// 這樣咱們就能夠在一個數據流中組合多個異步 action。
return dispatch(
makeASandwichWithSecretSauce('My Grandma')
).then(() =>
Promise.all([
dispatch(makeASandwichWithSecretSauce('Me')),
dispatch(makeASandwichWithSecretSauce('My wife'))
])
).then(() =>
dispatch(makeASandwichWithSecretSauce('Our kids'))
).then(() =>
dispatch(getState().myMoney > 42 ?
withdrawMoney(42) :
apologize('Me', 'The Sandwich Shop')
)
)
}
}
複製代碼
以上就是異步 Action ,thunk 是判別 action 的類型,若是 action 是函數,就調用這個函數,可是函數的內部能夠多種多樣。好比下面是一個獲取matching 中圖片下面的信息的異步操做所對應的 action,然而須要爲每個異步操做都如此定義一個 action,顯然 會有大量的action, 而且action 不易維護, 這是action 的反作用,也正是thunk 的缺點僅僅調用的函數。redux
官網上的描述redux-saga 是一個用於管理應用程序 Side Effect(反作用,例如異步獲取數據,訪問瀏覽器緩存等)的 library,它的目標是讓反作用管理更容易,執行更高效,測試更簡單
。 粗淺的使用後的感覺是很強大-各類狀況下的流程控制都有對應的api,這些api保證了更簡便的流程控制和易於測試的好處,因 thunk 插件仍是須要你本身來寫promise來保證各類異步和異常。那redux-saga 中間件中如何獲取state呢,更簡單select(selector, ...args)
api
const keyList = yield select(state => {});
複製代碼
Sagas 被實現爲 Generator functions,一旦 Promise 被 resolve,middleware 會恢復 Saga 接着執行,直到遇到下一個 yield。 點擊獲取如下詳細的demo例子promise
takeEvery(pattern, saga, ...args)
在發起(dispatch)到 Store 而且匹配 pattern 的每個 action 上派生一個 saga。import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
//...
import { demoSaga } from './demoSagas'
const store = createStore(
reducer,
applyMiddleware(createSagaMiddleware(demoSaga))
)
import { delay } from 'redux-saga'
import { put, takeEvery } from 'redux-saga/effects'
// demoSagas.js
// Our worker Saga: 將執行異步的 獲取用戶信息
export function* getUser() {
const user = yield call(fetch, {
// method: "POST"
resource: ''
});
}
// Our watcher Saga:
const watchGet = function* watchGet() {
yield takeEvery(getUserRequested, getUser);
}
cnost getActions = {
[getUserRequested]: state => {
return {
...state,
isLogging: true
};
},
[getUserSucceed]: (state, { payload: { avatar, name, email } }) => {
return {
...state,
isLogging: false,
user: {
avatar,
name,
email
}
};
},
[getUserFailed]: state => {
return {
...state,
isLogging: false
};
}
};
// rootSaga.js
export default function* rootSaga() {
import { all, call } from 'redux-saga/effects';
import { watchAppSagas } from './reducers/demoReducer';
export const sagas = function* rootSaga() {
yield all(
[
...watchAppSagas,
].map(call)
);
};
複製代碼