拆解Redux:从零手写一个状态管理器,彻底搞懂它的魔法!

大家好,我是小杨,一个在前端领域摸爬滚打了6年的"老油条"。今天想和大家聊聊Redux------这个曾经让我又爱又恨的状态管理库。很多新手觉得它复杂,但其实它的核心思想非常简单。为了彻底搞懂它,我决定带大家从零手写一个迷你Redux!

1. 为什么我需要Redux?一个血泪故事

还记得我刚接触复杂前端项目时,组件的状态传递像一团乱麻:

  • parentComponent 要传数据给 nestedChildComponent,得经过3层中间组件。
  • 兄弟组件之间修改状态?只能用回调地狱或者事件总线,代码难以维护。

直到我遇到了Redux,它的单一数据源单向数据流 像一束光拯救了我。但光会用不够,理解原理才能避免踩坑

2. Redux的三大核心:Store、Action、Reducer

先看官方定义?不,我用一个计数器例子解释:

javascript 复制代码
// 1. 定义Reducer(纯函数!)
function counterReducer(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

// 2. 创建Store(Redux.createStore的秘密)
const store = myCreateStore(counterReducer);

// 3. 触发Action(为什么必须用dispatch?)
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // 输出:1

关键点:

  • Reducer必须是纯函数,不能直接修改state!
  • Action是一个普通对象,但必须有type字段。
  • Store通过dispatch管理状态变更,避免随意修改。

3. 手写myCreateStore:20行代码揭示核心原理

Redux的魔法就藏在createStore里!下面是我的实现:

javascript 复制代码
function myCreateStore(reducer) {
  let currentState;
  const listeners = [];

  function getState() {
    return currentState;
  }

  function dispatch(action) {
    currentState = reducer(currentState, action);
    listeners.forEach(listener => listener()); // 通知所有订阅者
  }

  function subscribe(listener) {
    listeners.push(listener);
    return () => {
      const index = listeners.indexOf(listener);
      listeners.splice(index, 1);
    };
  }

  dispatch({ type: '@@INIT' }); // 初始化state
  return { getState, dispatch, subscribe };
}

为什么这样设计?

  • listeners 数组实现观察者模式,状态变化时自动更新UI(比如React的connect)。
  • 初始dispatch确保Reducer返回默认state。

4. 实战踩坑:我曾经犯过的3个错误

❌ 直接修改state

javascript 复制代码
// 错误写法!
function wrongReducer(state = { count: 0 }, action) {
  state.count += 1; // 直接修改了原state!
  return state;
}

后果: React组件不会重新渲染,因为浅比较发现引用未变。

❌ 在Reducer里执行异步操作

javascript 复制代码
// 错误示例!
function asyncReducer(state, action) {
  fetch('/api').then(() => { // 副作用!
    return { ...state, data: action.payload };
  });
}

正确做法: 用中间件(如redux-thunk)处理异步。

❌ 滥用Store存储局部状态

教训: 表单的临时输入值应该用组件state,而非全局Store。

5. 进阶:中间件(Middleware)机制揭秘

Redux最强大的特性是中间件。比如实现一个logger:

javascript 复制代码
function loggerMiddleware(store) {
  return function(next) {
    return function(action) {
      console.log('dispatching:', action);
      const result = next(action);
      console.log('next state:', store.getState());
      return result;
    };
  };
}

洋葱模型: 中间件的嵌套执行流程是Redux的灵魂。

6. 总结:Redux的设计哲学

  • 单向数据流:状态变化可预测。
  • 函数式编程:Reducer是纯函数,易于测试。
  • 发布订阅:高效管理状态依赖。

我的建议: 即使现在用Redux Toolkit或Zustand,理解Redux原理依然能让你更好地驾驭状态管理。

⭐ 写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

相关推荐
柠檬味的Cat2 小时前
使用腾讯云COS作为WordPress图床的实践
前端·github·腾讯云
Hilaku2 小时前
卷AI、卷算法、2026 年的前端工程师到底在卷什么?
前端·javascript·面试
非凡ghost2 小时前
AIMP(音乐播放软件)
前端·windows·音视频·firefox
xiaotao1312 小时前
Vite 完全学习指南
前端·vite·前端打包
弓.长.2 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-svg(CAPI) — 矢量图形组件
react native·react.js·harmonyos
军军君012 小时前
Three.js基础功能学习十五:智能黑板实现实例二
开发语言·前端·javascript·vue.js·3d·threejs·三维
IT枫斗者2 小时前
构建具有执行功能的 AI Agent:基于工作记忆的任务规划与元认知监控架构
android·前端·vue.js·spring boot·后端·架构
hotlinhao2 小时前
Nginx rewrite last 与 redirect 的区别——Vue history 模式短链接踩坑记录
前端·vue.js·nginx
ZC跨境爬虫2 小时前
海南大学交友平台开发实战day7(实现核心匹配算法+解决JSON请求报错问题)
前端·python·算法·html·json
下北沢美食家2 小时前
CSS面试题2
前端·css