做完React todos會發現,在React中畫面的呈現與資料內容都會是由state來管理,當要存的狀態越來越多的時候,state就會顯得有點難管理。React是單向資料流(Unidirectional Data Flow),最上層會有一個root component,它會keep住所有state和所有控制state的 function,再把這些state和function往下傳遞,所以很容易顯得有點繁瑣複雜。
Redux的出現可以幫忙管理這些繁瑣的事情,把state tree放在store,用actions發送事件給reducer來改變state,而在action和reducer中間還可以使用middleware做一些事情,middleware的部分後面會再特別介紹。今天會先簡單說明,Redux的三大原則,這樣我們之後實作,會更清楚這些觀念!
The state of your whole application is stored in an object tree within a single store.
前面有提到React管理畫面呈現或是資料內容的都是state,在Redux把它們統一存在一個叫做 store 的object tree中(也可以稱為state tree),所以說它是single source of truth,資料的唯一來源。
這邊以todos的state為例,再加上一個state記錄task完成狀態的fliter,以下就會是我們的store:
{
filter: 'SHOW_ALL',
todos: [
{
task: 'Install packages',
isCompleted: false
},
{
task: 'Add webpack.config.js',
isCompleted: false
},
{
task: 'Break UI into components',
isCompleted: false
}
]
}
The only way to change the state is to emit an action, an object describing what happened.
這邊的read only是指說state只能透過action去改變它,而不能任意的改變。Action是由一個plain object組成,透過這樣的指令,讓我們很容易做action的管理,紀錄發生action的順序,甚至也可以做undo的功能,這是透過用action來改變state的好處。
以下是action的寫法:
{
type: 'FINISH_TASK',
isCompleted: true
}
透過store發送action:
store.dispatch({
type: 'FINISH_TASK',
isCompleted: true
});
To specify how the state tree is transformed by actions, you write pure reducers.
Reducer就是pure function,action發送要改變的指令給reducer,reducer會收到action和前一個state當參數,並回傳新的state改變state,reducer不可以直接改變前一個state。而所謂的pure function,表示reducer return的值是要可以被預測的,不可以在function中做Math.random()或是fetch api,這些動作應該在action被dispatch時就先處理完成,必須保持 reducer is pure。
以下是reducer和設定reducer的方式:
// 處理filter的reducer
function filter(state = 'SHOW_ALL', action) {
switch (action.type) {
case 'SET_FILTER':
return action.filter;
default:
return state;
}
}
// 處理todos的reducer
function todos(state = [], action) {
... // 先略過內容
}
// 使用reducer來建立store,因為每個reducer都處理對應的state
import { combineReducers, createStore } from 'redux';
let reducer = combineReducers({ filter, todos });
let store = createStore(reducer);
上面這張圖說明Redux的整個流程,view就是我們的components,當user有一些操作或是某個特定情況,觸發action,store.dispatch要改變的事件內容,透過store傳給reducer,傳入prev state和action,reducer產生新的next state。當state tree被更新,就會引發view的re-render,這就是完整Redux的流程!
Redux最主要就是store、action、reducer這三個項目組成,先稍微理解這三個大原則,還有一些小細節可以說的,會再後面仔細介紹它們!