Redux的原理

Redux 工作原理

一句话概括:Redux 是一个集中式状态管理库,通过单向数据流管理应用状态,让状态变化变得可预测。

理解 Redux,只需要先掌握 Store、Action、Reducer、Dispatch 四个核心概念。

一、Redux 解决什么问题?

假设 React 应用中有多个组件需要共享用户信息:

css 复制代码
        App
       /   \
    Header  Main
      |      |
   Avatar  Profile

如果使用 React 自身的状态管理,可能需要通过 Props 层层传递,或者使用 Context。

Redux 提供了另一种方案:

把多个组件需要共享的状态统一放到 Store 中管理。

css 复制代码
       Redux Store
        userInfo
        count
        theme
          │
     ┌────┴────┐
     ▼         ▼
   Header     Profile

组件可以直接读取 Store 中的数据,并通过规定的方式更新状态。

注意:Redux 不是为了解决所有 Props 传递问题而设计的,它更适合管理具有一定复杂度的共享状态。


二、Redux 的四个核心概念

1. Store:状态仓库

Store 是保存应用状态的地方。

css 复制代码
{
  count: 0,
  user: {
    name: "Tom"
  }
}

整个 Redux 应用通常只有一个 Store。

2. Action:描述发生了什么

Action 是一个普通 JavaScript 对象,必须包含 type 属性。

bash 复制代码
{
  type: "counter/increment"
}

它只描述发生了什么,并不直接修改状态。

也可以携带数据:

bash 复制代码
{
  type: "counter/add",
  payload: 5
}

3. Reducer:决定如何更新状态

Reducer 是一个函数:

perl 复制代码
(state, action) => newState

例如:

javascript 复制代码
function counterReducer(state = { count: 0 }, action) {
  switch (action.type) {
    case "counter/increment":
      return {
        ...state,
        count: state.count + 1
      };

    default:
      return state;
  }
}

Reducer 根据旧状态和 Action 计算新状态。

Reducer 必须是纯函数,不能直接修改原有状态,也不应该包含异步操作等副作用。

4. Dispatch:发起状态更新

组件通过 dispatch 发送 Action。

bash 复制代码
store.dispatch({
  type: "counter/increment"
});

Redux 接收到 Action 后,就会调用 Reducer 计算新状态。


三、Redux 的完整工作流程

这是面试最重要的部分。

scss 复制代码
       React Component
              │
              │ 用户点击按钮
              ▼
         dispatch(action)
              │
              ▼
          Redux Store
              │
              │ 调用
              ▼
     reducer(state, action)
              │
              │ 返回新状态
              ▼
          Redux Store
              │
              │ 保存新状态
              ▼
       通知订阅者
              │
              ▼
     React-Redux 检查状态变化
              │
              ▼
     需要更新的组件重新渲染

核心:组件不能直接修改 Redux 状态,只能通过 dispatch → reducer → 新状态的方式更新。

这种机制叫做单向数据流(One-Way Data Flow) 。


四、用代码理解 Redux

先不引入 React,只看 Redux 本身。

javascript 复制代码
import { createStore } from "redux";

// 1. 定义 Reducer
function reducer(state = { count: 0 }, action) {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };

    default:
      return state;
  }
}

// 2. 创建 Store
const store = createStore(reducer);

// 3. 订阅状态变化
store.subscribe(() => {
  console.log("状态更新:", store.getState());
});

// 4. 获取状态
console.log(store.getState()); // { count: 0 }

// 5. 发送 Action
store.dispatch({ type: "increment" });

// 输出:状态更新:{ count: 1 }

注意:这里使用旧版 createStore 是为了方便理解原理。现代 Redux 官方推荐使用 Redux Toolkit 的 configureStore。

dispatch 内部发生了什么?

可以用一段简化代码理解 Redux:

scss 复制代码
function createStore(reducer) {
  let state;
  const listeners = [];

  function getState() {
    return state;
  }

  function dispatch(action) {
    // 1. 调用 Reducer,计算新状态
    state = reducer(state, action);

    // 2. 通知订阅者
    listeners.forEach(listener => listener());
  }

  function subscribe(listener) {
    listeners.push(listener);
  }

  // 初始化状态
  dispatch({ type: "@@INIT" });

  return {
    getState,
    dispatch,
    subscribe
  };
}

这是教学简化版,省略了订阅取消、异常检查等实现细节。

你会发现 Redux 的核心其实很简单:

  1. 使用闭包保存 state。
  2. 通过 dispatch 调用 Reducer 更新状态。
  3. 使用发布订阅模式通知状态变化。

五、Redux 和 React 如何配合?

Redux 本身与 React 无关。

React 项目通常通过 react-redux 连接 Redux。

主要使用两个 Hook:

useSelector:读取 Store 状态。

ini 复制代码
const count = useSelector(state => state.counter.count);

useDispatch:获取 dispatch 方法。

ini 复制代码
const dispatch = useDispatch();

dispatch({ type: "counter/increment" });

完整示例:

javascript 复制代码
function Counter() {
  const count = useSelector(state => state.counter.count);
  const dispatch = useDispatch();

  return (
    <div>
      <p>{count}</p>

      <button
        onClick={() => dispatch({ type: "counter/increment" })}
      >
        +1
      </button>
    </div>
  );
}

当 Store 状态更新时:

  1. React-Redux 收到 Store 的更新通知。
  2. useSelector 重新计算选中的值。
  3. 如果选中的结果发生变化,触发对应组件重新渲染。

注意:不是 Store 中任意状态发生变化,所有使用 Redux 的组件都会重新渲染。


六、Redux 如何处理异步操作?

Reducer 必须是纯函数,不能在里面直接发请求。

Redux 通过 Middleware(中间件) 处理异步逻辑。

例如使用 Redux Thunk:

ini 复制代码
const fetchUser = () => async (dispatch) => {
  const res = await fetch("/api/user");
  const user = await res.json();

  dispatch({
    type: "user/setUser",
    payload: user
  });
};

执行流程:

scss 复制代码
组件 dispatch(fetchUser())
          │
          ▼
     Thunk Middleware
          │
          ▼
       发起 API 请求
          │
          ▼
       获取响应数据
          │
          ▼
     dispatch 普通 Action
          │
          ▼
         Reducer
          │
          ▼
       Store 更新
          │
          ▼
       React 重新渲染

Middleware 的本质:拦截或增强 dispatch,使 Redux 能够处理异步操作、日志等逻辑。


七、Redux Toolkit 是什么?

现在开发 React 项目,通常使用 Redux Toolkit(RTK) ,而不是手动编写大量原生 Redux 代码。

RTK 是 Redux 官方推荐的工具集,主要简化:

传统 Redux Redux Toolkit
手写 Action Type 自动生成
手写 Action Creator 自动生成
手写 Reducer createSlice
手动保证不可变更新 使用 Immer 简化
手动配置 Store configureStore
手动配置异步逻辑 createAsyncThunk 等

例如:

javascript 复制代码
import { createSlice } from "@reduxjs/toolkit";

const counterSlice = createSlice({
  name: "counter",

  initialState: {
    count: 0
  },

  reducers: {
    increment(state) {
      state.count++;
    }
  }
});

export const { increment } = counterSlice.actions;

export default counterSlice.reducer;

这里的:

ini 复制代码
state.count++;

看起来违反了 Reducer 不能修改状态的原则。

实际上,Redux Toolkit 内部通过 Immer 将这种写法转换为不可变状态更新,因此不会直接修改原始状态。


八、面试如何回答 Redux 的工作原理?

可以直接用下面这段回答:

Redux 是一个基于单向数据流的状态管理库,主要包含 Store、Action、Reducer 三个核心概念。

Store 负责保存应用状态,组件通过 dispatch 发送 Action,Reducer 根据当前状态和 Action 计算并返回新状态,Store 保存新状态后通知订阅者。

在 React 中,React-Redux 通过订阅 Store 的变化,让使用 useSelector 的组件在选中数据发生变化时重新渲染。

Redux 内部主要依赖闭包保存状态、发布订阅模式通知更新,以及 Reducer 实现可预测的状态变更。对于异步操作,可以通过 Redux Thunk 等中间件处理。

现代项目一般使用 Redux Toolkit 来简化开发。

最后总结

掌握 Redux,最重要的其实只有两层:

第一层:工作流程

dispatch → action → reducer → store → React 更新

第二层:底层原理

  • 闭包:保存状态。
  • 发布订阅模式:通知状态变化。
  • 纯函数:保证状态更新可预测。
  • 中间件:扩展 dispatch 的能力。

你之前学过 Zustand,可以把两者联系起来理解:

Redux 和 Zustand 都是状态管理工具,但 Redux 更强调通过 Action 和 Reducer 规范状态变更,而 Zustand 通常允许通过 Store 中定义的 Action 函数直接调用 set 更新状态。

对于面试,理解 Redux 的核心工作流程和发布订阅机制,比死记大量 API 更有价值。

相关推荐
云和数据.ChenGuang2 小时前
name=“张三“ age=18 weight=100.3 print (name,age,weight)
java·服务器·前端
代码猎人2 小时前
前端怎么优化兼容性
前端
Nayana2 小时前
《Web 到 HarmonyOS》-- 进程、线程与通信:谁能通、怎么通
前端
叫我铁汁儿吧2 小时前
JS 中的this
前端
狂潮lister2 小时前
狂潮·元理论 | 第5篇:想为你的AI培养个性吗!哈哈哈……(6个测试,教你幻觉的正确玩法)
前端·人工智能
高晶2 小时前
2A3 单端甲类功放从零制作全攻略:电路设计、焊接调试到煲机维护一站式指南
前端·设计模式
deli0072 小时前
塔防游戏里怪物为什么绕远路?Canvas 实测 A* 寻路 20 波
前端
小万7422 小时前
WHO 心理自助指南深度解析:Step-by-Step 与 Doing What Matters in Times of Stress,用循证协议重构心理韧性
前端
代码猎人2 小时前
前端怎么优化用户体验
前端