摘要:增強除了解決復用問題,高階的另一個重要作用就是對原始的進行增強。就是典型的利用高階來增強的例子,它主要作用是使任意變成可以執行撤銷和重做的全新。
在Redux架構中,reducer是一個純函數,它的職責是根據previousState和action計算出新的state。在復雜應用中,Redux提供的combineReducers讓我們可以把頂層的reducer拆分成多個小的reducer,分別獨立地操作state樹的不同部分。而在一個應用中,很多小粒度的reducer往往有很多重復的邏輯,那么對于這些reducer,如何抽取公共邏輯,減少代碼冗余呢?這種情況下,使用高階reducer是一種較好的解決方案
reducer復用
我們將頂層的reduce拆分成多個小的reducer,肯定會碰到reducer復用問題。例如有A和B兩個模塊,它們的UI部分相似,此時可以通過配置不同的props來區別它們。那么這種情況下,A和B模塊能不能共用一個reducer呢?答案是否定的。我們先來看一個簡單reducer:
const LOAD_DATA = "LOAD_DATA"; const initialState = { ... }; function loadData() { return { type: LOAD_DATA, ... }; } function reducer(state = initialState, action) { switch(action.type) { case LOAD_DATA: return { ...state, data: action.payload }; default: return state; } }
如果我們將這個reducer綁定到A和B兩個不同模塊,造成的問題將會是,當A模塊調用loadData來分發相應的action時,A和B的reducer都會處理這個action,然后A和B的內容就完全一致了。
這里我們必需意識到,在一個應用中,不同模塊間的actionType必須是全局唯一的。
因此,要解決actionType唯一的問題,還有一個方法就是通過添加前綴的方式來做到:
function generateReducer(prefix, state) { const LOAD_DATA = prefix + "LOAD_DATA"; const initialState = { ...state, ...}; return function reducer(state = initialState, action) { switch(action.type) { case LOAD_DATA: return { ...state, data: action.payload }; default: return state; } } }
這樣只要A和B模塊分別調用generateReducer來生成相應的reducer,就能解決reducer復用的問題了。而對于prefix,我們可以根據自己的項目結構來決定,例如${頁面名稱}_${模塊名稱}。只要能夠保證全局唯一性,就可以寫成一種前綴。
reducer增強
除了解決復用問題,高階reducer的另一個重要作用就是對原始的reducer進行增強。redux-undo就是典型的利用高階reducer來增強reducer的例子,它主要作用是使任意reducer變成可以執行撤銷和重做的全新reducer。我們來看看它的核心代碼實現:
function undoable(reducer) { const initialState = { // 記錄過去的state past: [], // 以一個空的action調用reducer來產生當前值的初始值 present: reducer(undefined, {}), // 記錄后續的state future: [] }; return function(state = initialState, action) { const { past, present, future } = state; switch(action.type) { case "@@redux-undo/UNDO": const previous = past[past.length - 1]; const newPast = past.slice(0, past.length - 1); return { past: newPast, present: previous, future: [ present, ...future ] }; case "@@redux-undo/REDO": const next = future[0]; const newFuture = future.slice(1); return { past: [ ...past, present ], present: next, future: newFuture }; default: // 將其他action委托給原始的reducer處理 const newPresent = reducer(present, action); if(present === newPresent) { return state; } return { past: [ ...past, present ], present: newPresent, future: [] }; } }; }
有了這高階reducer,就可以對任意一個reducer進行封裝:
import { createStore } from "redux"; function todos(state = [], action) { switch(action.type) { case: "ADD_TODO": // ... } } const undoableTodos = undoable(todos); const store = createStore(undoableTodos); store.dispatch({ type: "ADD_TODO", text: "Use Redux" }); store.dispatch({ type: "ADD_TODO", text: "Implement Undo" }); store.dispatch({ type: "@@redux-undo/UNDO" });
查看高階reducer undoable的實現代碼可以發現,高階reducer主要通過下面3點來增強reducer:
能夠處理額外的action;
能夠維護更多的state;
將不能處理的action委托給原始reducer處理。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/105567.html
摘要:事件系統合成事件的綁定方式合成事件的實現機制事件委派和自動綁定。高階組件如果已經理解高階函數,那么理解高階組件也很容易的。例如我們常見的方法等都是高階函數。對測試群眾來說,從質量保證的角度出發,單元測試覆蓋率是 事件系統 合成事件的綁定方式 `Test` 合成事件的實現機制:事件委派和自動綁定。 React合成事件系統的委托機制,在合成事件內部僅僅是對最外層的容器進行了綁定,并且依賴...
摘要:學習之道簡體中文版通往實戰大師之旅掌握最簡單,且最實用的教程。前言學習之道這本書使用路線圖中的精華部分用于傳授,并將其融入一個獨具吸引力的真實世界的具體代碼實現。完美展現了的優雅。膜拜的學習之道是必讀的一本書。 《React 學習之道》The Road to learn React (簡體中文版) 通往 React 實戰大師之旅:掌握 React 最簡單,且最實用的教程。 showIm...
摘要:作為大型應用狀態管理最常用的工具。它是一個應用數據流框架,與框架類似。這是觸發變化的惟一途徑。在這個函數內部,被調用,其作用是監測是的。否則的話,認為只是一個普通的,將通過也就是進一步分發。到此源碼的主要部分學習結束。 Redux作為大型React應用狀態管理最常用的工具。它是一個應用數據流框架,與Flux框架類似。它是零依賴的,可以配合其他框架或者類庫一起使用。雖然在平時的工作中很多...
摘要:希望大家在這浮夸的前端圈里,保持冷靜,堅持每天花分鐘來學習與思考。 今天的React題沒有太多的故事…… 半個月前出了248個Vue的知識點,受到很多朋友的關注,都強烈要求再出多些React相前的面試題,受到大家的邀請,我又找了20多個React的使用者,他們給出了328道React的面試題,由我整理好發給大家,同時發布在了前端面試每日3+1的React專題,希望對大家有所幫助,同時大...
摘要:在前端基礎進階八深入詳解函數的柯里化一文中,我有分享柯里化相關的知識。雖然說高階組件與柯里化都屬于比較難以理解的知識點,但是他們組合在一起使用時并沒有新增更多的難點。 可能看過我以前文章的同學應該會猜得到當我用New的方法來舉例學習高階組件時,接下來要分享的就是柯里化了。高階組件與函數柯里化的運用是非常能夠提高代碼逼格的技巧,如果你有剩余的精力,完全可以花點時間學習一下。 在前端基礎進...
閱讀 1250·2021-11-23 09:51
閱讀 687·2021-11-19 09:40
閱讀 1354·2021-10-11 10:58
閱讀 2366·2021-09-30 09:47
閱讀 3741·2021-09-22 15:55
閱讀 2175·2021-09-03 10:49
閱讀 1266·2021-09-03 10:33
閱讀 708·2019-08-29 17:12