当前位置: 首页 > news >正文

Redux 原理深度剖析

1. Redux 实现

定义 Action 和 Reducer 类型,为了简便,先用JavaScript来演示。

1.1. 定义Action和Reducer类型

// 定义 Action 类型
/*** @typedef {Object} Action* @property {string} type*/// 定义 Reducer 类型
/*** @callback Reducer* @param {any} state* @param {Action} action* @returns {any}*/

Action 对象包含一个 type 属性,用于描述要执行的操作。

Reducer 是一个函数,接收当前状态和 Action,并返回新的状态。

1.2. 创建Store

// 创建 store
/*** @type {CreateStore}*/
function createStore(reducer, initialState, enhancer) {if (enhancer) {return enhancer(createStore)(reducer, initialState);}let state = initialState;let listeners = [];function getState() {return state;}function dispatch(action) {state = reducer(state, action);listeners.forEach(listener => listener());}function subscribe(listener) {listeners.push(listener);return () => {listeners = listeners.filter(l => l !== listener);};}return { getState, dispatch, subscribe };
}

createStore 函数用于创建 Redux store。

getState 方法返回当前状态。

dispatch 方法接收一个 Action,并使用 reducer 计算新状态。

subscribe 方法用于订阅状态变化。

1.3. 合并多个 Reducer

// 合并多个 reducer
/*** @param {Object<string, Reducer>} reducers* @returns {Reducer}*/
function combineReducers(reducers) {return (state = {}, action) => {const newState = {};for (const key in reducers) {newState[key] = reducers[key](state[key], action);}return newState;};
}

combineReducers 函数将多个 reducer 合并成一个,以便管理复杂的状态结构。

1.4. 组合函数

// 组合函数
/*** @param {...function} funcs* @returns {function}*/
function compose(...funcs) {if (funcs.length === 0) {return arg => arg;}if (funcs.length === 1) {return funcs[0];}return funcs.reduce((a, b) => (...args) => a(b(...args)));
}

compose 函数用于组合多个函数,从右到左依次执行。

1.5. 应用中间件

// 应用中间件
/*** @param {...Middleware} middlewares* @returns {function(CreateStore): CreateStore}*/
function applyMiddleware(...middlewares) {return createStore => (reducer, initialState) => {const store = createStore(reducer, initialState);let dispatch = store.dispatch;const middlewareAPI = {getState: store.getState,dispatch: action => dispatch(action),};const chain = middlewares.map(middleware => middleware(middlewareAPI));dispatch = compose(...chain)(store.dispatch);return {...store,dispatch,};};
}

applyMiddleware 函数用于应用中间件,增强 dispatch 方法。

1.6. Redux整体源码实现

// 定义 Action 类型
/*** @typedef {Object} Action* @property {string} type*/// 定义 Reducer 类型
/*** @callback Reducer* @param {any} state* @param {Action} action* @returns {any}*/// 定义 Store 类型
/*** @typedef {Object} Store* @property {function(): any} getState* @property {function(Action): void} dispatch* @property {function(function(): void): function(): void} subscribe*/// 创建 store
/*** @type {CreateStore}*/
function createStore(reducer, initialState, enhancer) {if (enhancer) {return enhancer(createStore)(reducer, initialState);}let state = initialState;let listeners = [];function getState() {return state;}function dispatch(action) {state = reducer(state, action);listeners.forEach(listener => listener());}function subscribe(listener) {listeners.push(listener);return () => {listeners = listeners.filter(l => l !== listener);};}return { getState, dispatch, subscribe };
}// 合并多个 reducer
/*** @param {Object<string, Reducer>} reducers* @returns {Reducer}*/
function combineReducers(reducers) {return (state = {}, action) => {const newState = {};for (const key in reducers) {newState[key] = reducers[key](state[key], action);}return newState;};
}// 组合函数
/*** @param {...function} funcs* @returns {function}*/
function compose(...funcs) {if (funcs.length === 0) {return arg => arg;}if (funcs.length === 1) {return funcs[0];}return funcs.reduce((a, b) => (...args) => a(b(...args)));
}// 应用中间件
/*** @param {...Middleware} middlewares* @returns {function(CreateStore): CreateStore}*/
function applyMiddleware(...middlewares) {return createStore => (reducer, initialState) => {const store = createStore(reducer, initialState);let dispatch = store.dispatch;const middlewareAPI = {getState: store.getState,dispatch: action => dispatch(action),};const chain = middlewares.map(middleware => middleware(middlewareAPI));dispatch = compose(...chain)(store.dispatch);return {...store,dispatch,};};
}// 示例代码
const initialState = { count: 0 };const counterReducer = (state = initialState, action) => {switch (action.type) {case 'INCREMENT':return { count: state.count + 1 };case 'DECREMENT':return { count: state.count - 1 };default:return state;}
};const loggerMiddleware = ({ getState }) => next => action => {console.log('will dispatch', action);next(action);console.log('state after dispatch', getState());
};const store = createStore(counterReducer,initialState,applyMiddleware(loggerMiddleware)
);store.subscribe(() => {console.log('state updated:', store.getState());
});store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'DECREMENT' });

2. 示例代码

2.1. 定义 Reducer 和初始状态

const initialState = { count: 0 };const counterReducer = (state = initialState, action) => {switch (action.type) {case 'INCREMENT':return { count: state.count + 1 };case 'DECREMENT':return { count: state.count - 1 };default:return state;}
};

counterReducer 是一个简单的 reducer,处理 INCREMENT 和 DECREMENT 两种 action。

2.2. 定义中间件

const loggerMiddleware = ({ getState }) => next => action => {console.log('will dispatch', action);next(action);console.log('state after dispatch', getState());
};

loggerMiddleware 是一个日志中间件,用于在 action 分发前后打印日志。

2.3. 创建 Store 并应用中间件

const store = createStore(counterReducer,initialState,applyMiddleware(loggerMiddleware)
);store.subscribe(() => {console.log('State updated:', store.getState());
});store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'DECREMENT' });

创建 store 并应用 loggerMiddleware 中间件。

订阅状态变化并分发两个 action。

3. 将 Redux 与 React 结合

3.1. 创建自定义 Hook

import React from 'react';
import { useSyncExternalStore } from 'react';/*** 自定义 Hook,使用 useSyncExternalStore 订阅 Redux store 的状态变化* @param {Store} store* @returns {any} 当前状态*/
function useReduxStore(store) {return useSyncExternalStore(store.subscribe, // 订阅状态变化store.getState, // 获取当前状态store.getState // SSR 期间获取当前状态 (此处简化处理));
}

useReduxStore 是一个自定义 Hook,利用 useSyncExternalStore 订阅 Redux store 的状态变化。

3.2. 编写示例组件

function Counter() {const state = useReduxStore(store); // 使用自定义 Hook 获取 Redux 状态return (<div><p>Count: {state.count}</p><button onClick={() => store.dispatch({ type: 'INCREMENT' })}>Increment</button><button onClick={() => store.dispatch({ type: 'DECREMENT' })}>Decrement</button></div>);
}

Counter 组件使用 useReduxStore Hook 获取当前状态,并通过 Redux store 分发动作。

3.3. 渲染组件

import { createRoot } from 'react-dom/client';const container = document.getElementById('root');
const root = createRoot(container);
root.render(<Counter />);
// 将 Counter 组件渲染到页面

使用 createRoot 渲染 Counter 组件到页面上的 DOM 节点中。

4. Mantine 的状态 ts 实现

import { useSyncExternalStore } from 'react';export type MantineStoreSubscriber<Value> = (value: Value) => void;
type SetStateCallbackValue = (value: Value) => Value;export interface MantineStore<Value> {getState: () => Value;setState: (value: Value | SetStateCallbackValue) => void;updateState: (value: Value | SetStateCallbackValue) => void;initialize: (value: Value) => void;subscribe: (callback: MantineStoreSubscriber<Value>) => () => void;
}export type MantineStoreValue<Store extends MantineStore<any>> = ReturnType<Store['getState']>;export function createStore<Value extends Record<string, any>>(initialState: Value
): MantineStore<Value> {let state = initialState;let initialized = false;const listeners = new Set<MantineStoreSubscriber<Value>>();return {getState() {return state;},updateState(value) {state = typeof value === 'function' ? value(state) : value;},setState(value) {this.updateState(value);listeners.forEach((listener) => listener(state));},initialize(value) {if (!initialized) {state = value;initialized = true;}},subscribe(callback) {listeners.add(callback);return () => listeners.delete(callback);},};
}export function useStore<Store extends MantineStore<any>>(store: Store) {return useSyncExternalStore<MantineStoreValue<Store>>(store.subscribe,() => store.getState(),() => store.getState());
}

5. Redux 的其他概念

异步的支持,因为 reducer 的设计,导致处理过程是依照纯函数和同步函数处理的,所以我们需要额外考虑异步的事情,使用 redux-thunk、redux-sage的方案。

相关文章:

  • PX4无人机|MID360使用FAST_LIO,实现自主定位及定点——PX4无人机配置流程(五)
  • CTFshow-PWN-栈溢出(pwn56-pwn59)
  • 2025-06-14【视觉】批量筛选图集中包含某种物体对象的方法
  • 解决ModuleNotFoundError: No module named ‘open_clip‘
  • 多项目状态如何集中监控与汇总
  • 基于开源AI大模型与智能工具的优质内容引流策略研究——以AI智能名片及S2B2C商城小程序源码应用为例
  • 禾川伺服驱动器与EtherCAT主站转Profinet网关的双向数据交换
  • 纯 CSS 实现的的3种扫光效果
  • 基于STM32人脸识别系统
  • (LeetCode每日一题) 2566. 替换一个数字后的最大差值 ( 贪心 )
  • pytorch2.6安装
  • React项目常用目录结构
  • ResizeObserver的错误
  • 人工智能学习23-BP-图像编码
  • 5.5.1_哈夫曼树
  • UltraISO绿色便携版v9 下载与安装教程
  • StampedLock入门教程
  • 在线五子棋
  • 从大模型到 AI 应用,一共需要几步?
  • 【项目实训#10】HarmonyOS API文档RAG检索系统后端实现
  • 网站维护成本/百度收录提交入口网址
  • 有没有做网站的/如何进行网站的推广
  • 网站开发论文英文资料/seo案例模板
  • wordpress改不了语言/搜索引擎seo关键词优化方法
  • 漯河英文网站建设/域名解析
  • 重庆网站开发/推荐友情链接