Redux 數(shù)據(jù)流

2021-09-16 09:51 更新

數(shù)據(jù)流

嚴(yán)格的單向數(shù)據(jù)流是 Redux 架構(gòu)的設(shè)計(jì)核心。

這意味著應(yīng)用中所有的數(shù)據(jù)都遵循相同的生命周期,這樣可以讓?xiě)?yīng)用變得更加可預(yù)測(cè)且容易理解。同時(shí)也鼓勵(lì)做數(shù)據(jù)范式化,這樣可以避免使用多個(gè),獨(dú)立的無(wú)法相互引用的重復(fù)數(shù)據(jù)。

如何這些理由還不足以今你信服,讀一下 動(dòng)機(jī)Flux 案例,這里面有更加詳細(xì)的單向數(shù)據(jù)流優(yōu)勢(shì)分析。雖然 Redux 就不是嚴(yán)格意義上的 Flux,但它們有共同的設(shè)計(jì)思想。

Redux 應(yīng)用中數(shù)據(jù)的生命周期遵循下面 4 個(gè)步驟:

  1. 調(diào)用store.dispatch(action)。

action 就是一個(gè)描述“發(fā)生了什么”的普通對(duì)象。比如:

 { type: 'LIKE_ARTICLE', articleId: 42 };
 { type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'Megan' } };
 { type: 'ADD_TODO', text: 'Read the Redux docs.'};

可以把 action 理解成新聞的摘要。如 “瑪麗喜歡42號(hào)文章?!?或者 “任務(wù)列表里添加了'學(xué)習(xí) Redux 文檔'”。

你可以在任何地方調(diào)用 store.dispatch(action),包括組件中、XHR 回調(diào)中、甚至定時(shí)器中。

  1. Redux store 調(diào)用傳入的 reducer 函數(shù)。

Store 會(huì)把兩個(gè)參數(shù)傳入 reducer,當(dāng)前的 state 樹(shù)和 action。例如,在這個(gè) todo 應(yīng)用中,根 reducer 可能接收這樣的數(shù)據(jù):

 // 當(dāng)前應(yīng)用的 state(todos 列表和選中的過(guò)濾器)
 let previousState = {
   visibleTodoFilter: 'SHOW_ALL',
   todos: [{
     text: 'Read the docs.',
     complete: false
   }]
 };

 // 將要執(zhí)行的 action(添加一個(gè) todo)
 let action = {
   type: 'ADD_TODO',
   text: 'Understand the flow.'
 };

 // render 返回處理后的應(yīng)用狀態(tài)
 let nextState = todoApp(previousState, action);

注意 reducer 是純函數(shù)。它應(yīng)該是完全可預(yù)測(cè)的:多次傳入相同的輸入必須產(chǎn)生相同的輸出。它不應(yīng)做有副作用的操作,如 API 調(diào)用或路由跳轉(zhuǎn)。這些應(yīng)該在 dispatch action 前發(fā)生。

  1. 根 reducer 應(yīng)該把多個(gè)子 reducer 輸出合并成一個(gè)單一的 state 樹(shù)。

根 reducer 的結(jié)構(gòu)完全由你決定。Redux 原生提供combineReducers()輔助函數(shù),來(lái)把根 reducer 拆分成多個(gè)函數(shù),用于分別處理 state 樹(shù)的一個(gè)分支。

下面演示 combineReducers() 如何使用。假如你有一個(gè) todos 列表,使用當(dāng)前的選擇過(guò)濾器來(lái)追蹤兩個(gè) 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
 });

當(dāng)你觸發(fā) action 后,combineReducers 返回的 todoApp 會(huì)負(fù)責(zé)調(diào)用兩個(gè) reducer:

 let nextTodos = todos(state.todos, action);
 let nextVisibleTodoFilter = visibleTodoFilter(state.visibleTodoFilter, action);

然后會(huì)把兩個(gè)結(jié)果集合并成一個(gè) state 樹(shù):

 return {
   todos: nextTodos,
   visibleTodoFilter: nextVisibleTodoFilter
 };

雖然 combineReducers() 是一個(gè)很方便的輔助工具,你也可以選擇不用;你可以自行實(shí)現(xiàn)自己的根 reducer!

  1. Redux store 保存了根 reducer 返回的完整 state 樹(shù)。

這個(gè)新的樹(shù)就是應(yīng)用的下一個(gè) state!所有訂閱 store.subscribe(listener) 的監(jiān)聽(tīng)器都將被調(diào)用;監(jiān)聽(tīng)器里可以調(diào)用 store.getState() 獲得當(dāng)前 state。

現(xiàn)在,可以應(yīng)用新的 state 來(lái)更新 UI。如果你使用了 React Redux 這類的綁定庫(kù),這時(shí)就應(yīng)該調(diào)用 component.setState(newState) 來(lái)更新。

下一步

現(xiàn)在你已經(jīng)理解了 Redux 如何工作,是時(shí)候結(jié)合 React 開(kāi)發(fā)應(yīng)用了。

高級(jí)用戶使用注意

如果你已經(jīng)熟悉了基礎(chǔ)概念且完成了這個(gè)教程,可以學(xué)習(xí)高級(jí)教程中的異步數(shù)據(jù)流,你將學(xué)到如何使用 middleware 在 異步 action 到達(dá) reducer 前處理它們。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)