嚴格的單向數(shù)據(jù)流是 Redux 架構(gòu)的設計核心。
這意味著應用中所有的數(shù)據(jù)都遵循相同的生命周期,這樣可以讓應用變得更加可預測且容易理解。同時也鼓勵做數(shù)據(jù)范式化,這樣可以避免使用多個,獨立的無法相互引用的重復數(shù)據(jù)。
如何這些理由還不足以今你信服,讀一下 動機 和 Flux 案例,這里面有更加詳細的單向數(shù)據(jù)流優(yōu)勢分析。雖然 Redux 就不是嚴格意義上的 Flux,但它們有共同的設計思想。
Redux 應用中數(shù)據(jù)的生命周期遵循下面 4 個步驟:
調(diào)用store.dispatch(action)
。
action 就是一個描述“發(fā)生了什么”的普通對象。比如:
{ type: 'LIKE_ARTICLE', articleId: 42 };
{ type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'Megan' } };
{ type: 'ADD_TODO', text: 'Read the Redux docs.'};
可以把 action 理解成新聞的摘要。如 “瑪麗喜歡42號文章?!?或者 “任務列表里添加了'學習 Redux 文檔'”。
你可以在任何地方調(diào)用 store.dispatch(action)
,包括組件中、XHR 回調(diào)中、甚至定時器中。
Redux store 調(diào)用傳入的 reducer 函數(shù)。
Store 會把兩個參數(shù)傳入 reducer,當前的 state 樹和 action。例如,在這個 todo 應用中,根 reducer 可能接收這樣的數(shù)據(jù):
// 當前應用的 state(todos 列表和選中的過濾器)
let previousState = {
visibleTodoFilter: 'SHOW_ALL',
todos: [{
text: 'Read the docs.',
complete: false
}]
};
// 將要執(zhí)行的 action(添加一個 todo)
let action = {
type: 'ADD_TODO',
text: 'Understand the flow.'
};
// render 返回處理后的應用狀態(tài)
let nextState = todoApp(previousState, action);
注意 reducer 是純函數(shù)。它應該是完全可預測的:多次傳入相同的輸入必須產(chǎn)生相同的輸出。它不應做有副作用的操作,如 API 調(diào)用或路由跳轉(zhuǎn)。這些應該在 dispatch action 前發(fā)生。
根 reducer 應該把多個子 reducer 輸出合并成一個單一的 state 樹。
根 reducer 的結(jié)構(gòu)完全由你決定。Redux 原生提供combineReducers()
輔助函數(shù),來把根 reducer 拆分成多個函數(shù),用于分別處理 state 樹的一個分支。
下面演示 combineReducers()
如何使用。假如你有一個 todos 列表,使用當前的選擇過濾器來追蹤兩個 reducers(原文:and the currently selected filter setting to keep track of with two reducers):
function todos(state = [], action) {
// 省略處理邏輯...
return nextState;
}
function visibleTodoFilter(state = 'SHOW_ALL', action) {
// 省略處理邏輯...
return nextState;
}
let todoApp = combineReducers({
todos,
visibleTodoFilter
});
當你觸發(fā) action 后,combineReducers
返回的 todoApp
會負責調(diào)用兩個 reducer:
let nextTodos = todos(state.todos, action);
let nextVisibleTodoFilter = visibleTodoFilter(state.visibleTodoFilter, action);
然后會把兩個結(jié)果集合并成一個 state 樹:
return {
todos: nextTodos,
visibleTodoFilter: nextVisibleTodoFilter
};
雖然 combineReducers()
是一個很方便的輔助工具,你也可以選擇不用;你可以自行實現(xiàn)自己的根 reducer!
Redux store 保存了根 reducer 返回的完整 state 樹。
這個新的樹就是應用的下一個 state!所有訂閱 store.subscribe(listener)
的監(jiān)聽器都將被調(diào)用;監(jiān)聽器里可以調(diào)用 store.getState()
獲得當前 state。
現(xiàn)在,可以應用新的 state 來更新 UI。如果你使用了 React Redux 這類的綁定庫,這時就應該調(diào)用 component.setState(newState)
來更新。
現(xiàn)在你已經(jīng)理解了 Redux 如何工作,是時候結(jié)合 React 開發(fā)應用了。
高級用戶使用注意
如果你已經(jīng)熟悉了基礎概念且完成了這個教程,可以學習高級教程中的異步數(shù)據(jù)流,你將學到如何使用 middleware 在 異步 action 到達 reducer 前處理它們。
更多建議: