Redux 作為前端經典狀態管理庫,核心解決 “組件間狀態共享” 與 “狀態變更可追溯” 問題,適配大型 React 專案。這篇文章我透過結合手寫核心邏輯與現代工具 RTK,拆解 Redux 原理,明晰 “底層原理” 與 “高效開發” 的協同路徑。
Redux 遵循單向數據流,狀態變更需經 Action → Reducer → Store
流程,確保可預測性。
Action 是觸發狀態變更的 “入口”,本質是平面物件(需 isPlainObject
驗證),核心作用是描述 “發生了什麼操作”,可透過 payload
攜帶數據。
type
屬性:標識操作類型(如 INCREMENT
),類型無強制約束(字串、Symbol 均可),大型專案建議單獨維護(如 actionTypes.js
)避免硬編碼。// 基礎 Action 結構
const incrementAction = {
type: "INCREMENT",
payload: 1
};
// 生成“增加計數”的 Action
const increment = (step) => ({
type: "INCREMENT",
payload: step
});
bindActionCreators
:自動發送 Actionstore.dispatch(action)
觸發變更,bindActionCreators
可增強 Action Creator,使其創建後自動發送,簡化代碼。function getAutodisPatchActionCreator(actionCreator, dispatch) {
return (...args) => {
const action = actionCreator(...args);
dispatch(action);
};
}
export default function bindActionCreators(actionCreators, dispatch) {
if (typeof actionCreators === 'function') {
return getAutodisPatchActionCreator(actionCreators, dispatch);
}
const result = {};
for (const key in actionCreators) {
const creator = actionCreators[key];
if (typeof creator === 'function') {
result[key] = getAutodisPatchActionCreator(creator, dispatch);
}
}
return result;
}
Reducer 是 Redux 的 “狀態計算核心”,接收當前 state
和 Action,返回新狀態(不可修改原狀態),決定 “如何根據操作變更狀態”。
必須是純函數:保障 Redux 可預測性,要求:
state
和 action
;初始化狀態的技巧
創建 Store 時,Redux 自動發送初始化 Action(類型為 @@redux/INIT + 隨機字串
,由 ActionTypes.INIT()
生成),此時 Reducer 接收 state = undefined
,可透過參數預設值初始化狀態:
// 計數狀態管理示例
function countReducer(state = 0, action) {
switch (action.type) {
case "INCREMENT":
return state + action.payload;
case "DECREMENT":
return state - action.payload;
default:
return state;
}
}
combineReducers
:拆分複雜 ReducercombineReducers
合併為根 Reducer。export default function combineReducers(reducers) {
validateReducers(reducers);
return function (state = {}, action) {
const newState = {};
for (const key in reducers) {
if (reducers.hasOwnProperty(key)) {
const subReducer = reducers[key];
newState[key] = subReducer(state[key], action);
}
}
return newState;
};
}
示例(合併 “使用者” 與 “計數” 模組):
const rootReducer = combineReducers({
user: userReducer,
count: countReducer
});
// Store 狀態結構:{ user: {...}, count: 0 }
Store 是 Redux 中 “唯一的狀態容器”,透過 createStore(reducer)
創建,封裝狀態存儲、發送 Action、監聽狀態變化的核心能力。
getState()
:獲取當前狀態currentState
,是組件獲取狀態的唯一途徑:function getState() {
return currentState;
}
dispatch(action)
:觸發狀態變更type
);listeners
),通知狀態變更。function dispatch(action) {
if (!isPlainObject(action)) {
throw new TypeError("action must be a plain object");
}
if (action.type === undefined) {
throw new TypeError("action must has a property of type");
}
currentState = currentReducer(currentState, action);
for (const listener of listeners) {
listener();
}
}
subscribe(listener)
:監聽狀態變化dispatch
觸發後執行所有監聽器;返回 “取消監聽” 函數,避免記憶體洩漏。function subscribe(listener) {
listeners.push(listener);
let isRemoved = false;
return function () {
if (isRemoved) return;
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
isRemoved = true;
};
}
ActionTypes.INIT()
),觸發 Reducer 執行,透過參數預設值完成狀態初始化(無需手動傳預設狀態)。isPlainObject(obj)
:驗證平面物件(__proto__
指向 Object.prototype
),避免非標準物件(如陣列、類實例)導致邏輯異常。export default function isPlainObject(obj) {
if (typeof obj !== "object") return false;
return Object.getPrototypeOf(obj) === Object.prototype;
}
ActionTypes
:生成隨機初始化 Action 類型(如 @@redux/INIT + 隨機字串
),避免與業務 Action 衝突。function getRandom(length) {
return Math.random().toString(36).slice(2, length + 2).split("").join(".");
}
export default {
INIT() { return `@@redux/INIT${getRandom(6)}`; },
UNKNOWN() { return `@@redux/PROBE_UNKNOWN_ACTION${getRandom(6)}`; }
};
dispatch
能力Redux 核心僅支持同步 Action,處理異步操作(如介面請求)需透過中介軟體擴展 dispatch
功能。
中介軟體本質是 “函數鏈”,在 dispatch
觸發 Action 後、Reducer 執行前,插入自定義邏輯(如異步請求、日誌、錯誤捕獲)。常見中介軟體:
redux-thunk
:支持函數式 Action(Action 可返回函數,內部執行異步操作);redux-saga
:用 Generator 管理複雜異步流程(如介面重試、競態處理)。核心原理:中介軟體包裝 store.dispatch
,支持非標準 Action(如函數、Promise),待異步完成後,發送真正的 “同步 Action” 觸發狀態變更。
現代開發中,Redux 官方推出 Redux Toolkit(RTK) ,封裝 createSlice
(合併 Action 與 Reducer)、configureStore
(簡化 Store 創建,內置中介軟體)等工具,大幅減少重複代碼(無需手動寫 combineReducers
、bindActionCreators
),已成為 Redux 開發的推薦方案。
createSlice
自動生成 Action 與 Reducer),適合快速迭代的專案。createSlice
:合併 Action 類型、Reducer、Action Creator,自動生成 Action(如 increment
)。import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: (state, action) => state + action.payload,
decrement: (state, action) => state - action.payload,
},
});
// 自動生成 Action Creator:counterSlice.actions.increment
configureStore
:簡化 Store 創建,內置 redux-thunk
、redux-devtools
等中介軟體。import { configureStore } from '@reduxjs/toolkit';
const store = configureStore({
reducer: rootReducer,
});
slice.actions
)觸發 Action;dispatch
傳遞 Action 至 Reducer;store.getState()
)。Redux 透過分離 Action、Reducer、Store,讓狀態變更可追溯、可測試,尤其適配大型專案的複雜狀態管理。
Redux 的核心價值在於規範狀態管理流程,手寫實現揭示其 “簡潔而嚴謹” 的邏輯(純函數、單向數據流);RTK 則是站在 Redux 肩膀上的 “現代工具”,讓開發更高效。
對於我們開發者而言:
二者相輔相成,共同構建前端狀態管理的 “清晰脈絡”。
如果您覺得這篇文章對您有幫助,歡迎按讚和收藏,大家的支持是我繼續創作優質內容的動力🌹🌹🌹也希望您能在😉😉😉我的首頁 😉😉😉找到更多對您有幫助的內容。