Skip to main content

Redux

Redux 是一个基于 Flux 架构函数式编程(纯函数/不可变数据)的状态管理库。它的核心思想是:单一数据源、状态只读、使用纯函数(Reducer)来执行修改。通过严苛的规范,换取了极强的状态可预测性和时间旅行(Time Travel)调试能力。

1. 核心工作流与三大原则

Redux 的工作流非常严谨,是典型的单向数据流View (视图) -> 触发 Action (动作) -> Dispatch (派发) -> Reducer (纯函数计算) -> 返回新 State -> 触发视图更新

面试必考:Redux 的三大原则

  1. 单一数据源 (Single Source of Truth):整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
  2. State 是只读的 (Read-only):唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
  3. 使用纯函数来执行修改 (Changes are made with pure functions):为了描述 action 如何改变 state tree ,你需要编写 reducers。Reducer 必须是纯函数:即 (oldState, action) => newState,绝对不能修改原状态,必须返回一个全新的对象!

2. Redux 中间件 (Middleware) 原理

如果面试官问:“既然 Reducer 必须是纯函数,那网络请求、日志打印这种副作用 (Side Effects) 代码该写在哪里?” 答案是:中间件 (Middleware)

中间件的核心本质是:劫持并重写 store.dispatch 方法。 在 action 发出之后,到达 reducer 之前,中间件可以拦截这个 action,进行异步请求、日志打印、甚至是取消派发。

高频手写题:实现 Redux 的 compose 函数 Redux 底层通过 compose 将多个中间件洋葱模型般地嵌套起来。它的核心是利用 Array.prototype.reduce

function compose(...funcs) {
if (funcs.length === 0) return (arg) => arg;
if (funcs.length === 1) return funcs[0];

// 面试手写重点:利用 reduce 把前一个函数的执行结果作为后一个函数的入参
return funcs.reduce(
(a, b) =>
(...args) =>
a(b(...args)),
);
}

// 执行过程示例:
// compose(f, g, h)(x) === f(g(h(x)))

经典中间件对比:Redux-Thunk vs Redux-Saga

  • redux-thunk
    • 原理:判断如果传给 dispatch 的 action 是一个函数,就把 dispatch 传给这个函数执行;如果是对象,就直接放行。
    • 优点:极简,学习成本低。
    • 缺点:把异步逻辑写成了回调地狱,极难处理复杂的竞态条件和任务取消。
  • redux-saga (大厂重度依赖)
    • 原理:基于 ES6 的 Generator 机制实现。
    • 优点:将异步操作完全从业务逻辑中剥离,变成了“同步”的写法;提供了极度强大的控制流(如 takeLatest 防抖、race 竞态、cancel 取消任务)。

3. react-redux 的底层实现

Redux 本身是框架无关的,能在 React 里丝滑使用,全靠 react-redux 库搭桥。

核心设计:Context + 发布订阅

  1. <Provider>:在应用最顶层,通过 React Context 将 store 实例传递给整棵组件树。
  2. useSelector (或早期的 connect)
    • 内部调用 store.getState() 获取状态片段。
    • 内部调用 store.subscribe() 订阅 store 的变化。当状态改变时,比对当前片段是否发生变化,如果变了,强制当前组件重新渲染。

面试加分项:React 18 下的重构 在早期的 react-redux 中,由于使用了外部的发布订阅模式,在 React 的并发渲染(Concurrent Mode)下很容易出现“页面撕裂(Tearing)”(即同一个状态在页面上半部分和下半部分渲染出不同的值)。 为了解决这个问题,React 18 专门推出了一个官方 Hook:useSyncExternalStore。目前 react-redux 的底层已经全面切换到了这个 Hook,完美解决了外部状态库在并发模式下的撕裂问题。