In React JS Tutorials, lectures from 9. html
From: React高級篇(一)從Flux到Redux,react-reduxreact
從Flux到Redux,再到react-redux,從這個簡短歷程中,咱們能夠看到框架設計上的演進,而redux + react-redux也是React開發萬家桶的標配。git
到了這裏,能夠忘記Flux啦~github
[React] 07 - Flux: react communicates with mongodb mongodb
[React] 11 - Redux: reduxredux
[React] 12 - Redux: async & middleware數組
[React] 13 - Redux: react-redux架構
[React] 14 - Redux: Redux Sagamvc
[React] 15 - Redux: TodoMVC 框架
文檔:https://redux.js.org/basics/example-todo-list
結合Redux-saga 中文文檔,乃高手必備之物。
江湖有云:先實踐一下,而後再看以上文檔和示例代碼。
詳述:[React] 07 - Flux: react communicates with mongodb
實現的思路要點:
1. 在store中有一個數組(state)來表現new item。
2. 點擊按鈕,發送信號(action),改變狀態,view監聽到狀態後刷新(從新表現items)
dispatch與store的問題,過於靈活。
參考:[React] 02 - Intro: why react and its design pattern - 背後的思想:一步一步進化到 Redux
學習: 《看漫畫,學 Redux》 —— A cartoon intro to Redux
問題1:store 的代碼沒法被熱替換,除非清空當前的狀態
改變下store的代碼,狀態沒了!不利於調試(熱替換)。
分開保存便可。
問題2:每次觸發 action 時狀態對象都被直接改寫了
舊狀態管理不穩定,很差實現 「跳回到這個對象以前的某個狀態(想象一個撤銷功能)」。
當一個 action 須要 store 響應時,將狀態拷貝一份並在這份拷貝的狀態上作出修改。
問題3:沒有合適的位置引入第三方插件
一個簡單的例子就是日誌。好比說你但願 console.log() 每個觸發的 action 同時 console.log() 這個 action 被響應完成後的狀態。
在 Flux 中,你只能訂閱(subscribe) dispatcher 的更新和每個 store 的變更。
可是這樣就侵入了業務代碼,這樣的日誌功能不是一個第三方插件可以輕易實現的。
(1) 將這個架構的部分功能包裝進其餘的對象(中間件)中將使得咱們的需求變得更容易實現;
Goto: [React] 12 - Redux: async & middleware
(2) 使用一個樹形結構來組織全部改變狀態的邏輯。
學習: 《看漫畫,學 Redux》 —— A cartoon intro to Redux
1. Action creators
保留了 Flux 中 action creator 的概念。
Redux 中的 action creator 不會直接把 action 發送給 dispatcher,而是返回一個格式化好的 JavaScript 對象。
2. The store
Redux 中的 store 首先會保存整個應用的全部狀態,而後將判斷 "哪一部分狀態須要改變" 的任務分配下去。
而以 root reducer 爲首的 reducer 們將會承擔這個任務。
store 已經徹底接管了 dispatch 相關的工做。
3. The reducers
當 store 須要知道一個 action 觸發後狀態須要怎麼改變時,他會去詢問 reducer。
Root reducer 會根據狀態對象的鍵(key)將整個狀態樹進行拆分,而後將拆分後的每一塊子狀態傳到知道該怎麼響應的子 reducer 那裏進行處理。
【狀態樹,子狀態,子 reducer】
4. 拷貝state後修改
這是 Redux 的核心思想之一。不直接修改整個應用的狀態樹,而是將狀態樹的每一部分進行拷貝並修改拷貝後的部分,而後將這些部分從新組合成一顆新的狀態樹。
子 reducers 會把他們建立的副本傳回給根 reducer,而根 reducer 會把這些副本組合起來造成一顆新的狀態樹。最後根 reducer 將新的狀態樹傳回給 store,store 再將新的狀態樹設爲最終的狀態。
若是你有一個小型應用,你可能 只有一個 reducer 對整個狀態樹進行拷貝並做出修改。
又或者你有一個超大的應用,你可能會有 若干個 reducers 對整個狀態樹進行修改。這也是 Flux 和 Redux 的另外一處區別。
在 Flux 中,store 並不須要與其餘 store 產生關聯,並且 store 的結構是扁平的。
而在 Redux 中,reducers 是有層級結構的。這種層級結構能夠有若干層,就像組件的層級結構那樣。
4.1 Immutable for Object
4.2 concat for Array
4.3 filter for Array
4.4 定製化 硬拷貝
詳情請見: [React] 11 - Redux: redux
React JS Tutorials - Redux部分
import { createStore } from "redux";
(2) 接收到動做信號
const reducer = (initialState=0, action) => {
...
}
const store = createStore(reducer, 1)
(3) 觸發事件
/* 每次 改變的時候會執行一次這個函數 */
store.subscribe(() => {
console.log("store changed", store.getState());
})
(1) 發生一次用戶動做
// store.dispatch({type: "INC"})
state
添加了更多的動做,觸發了更多的事件。
Jeff: 多reducer的狀況的處理方式。
import { combineReducers, createStore } from "redux";
/////////////////////////////////////////////////////////////////////////////////////////////////////// /**
* 放在單獨的文件裏爲好
*/
const userReducer = (state={}, action) => { switch(action.type) { case "SET_NAME": { return {...state, name: action.payload}; break; } case "SET_AGE": { return {...state, age: action.payload}; break; } } return state; } // I would live in a separate file const tweetsReducer = (state=[], action) => { switch(action.type) { case "ADD_TWEET": { return state.concat({ id: Date.now(), //fake an ID by using a timestamp text: action.payload, }); break; } } return state; } ------------------------------------------------------------------------------------------------------- const reducers = combineReducers({ user: userReducer, tweets: tweetsReducer })
//////////////////////////////////////////////////////////////////////////////////////////////////////// const store = createStore(reducers) // state的默認值能夠做爲第二個參數,或者放在reducer的第一個init state定義
////////////////////////////////////////////////////////////////////////////////////////////////////////
store.subscribe(() => { console.log("store changed", store.getState()); })
//////////////////////////////////////////////////////////////////////////////////////////////////////// store.dispatch({type: "SET_NAME", payload: "Will"}) store.dispatch({type: "SET_AGE", payload: 35}) store.dispatch({type: "SET_AGE", payload: 34}) store.dispatch({type: "ADD_TWEET", payload: "OMG LIKE LOL"}) store.dispatch({type: "ADD_TWEET", payload: "I am so like seriously like totally like right now"})
請注意:做爲對比,上例中的store.dispatch通常會寫在onClick中,由用戶觸發,以下。
const render = () => ReactDOM.render( <Counter value={store.getState()} onIncrement={() => store.dispatch({ type: 'INCREMENT' })} onDecrement={() => store.dispatch({ type: 'DECREMENT' })} />, rootEl )
詳見請見:[React] 12 - Redux: async & middleware
詳見請見:[React] 13 - Redux: react-redux