Redux 深入解析

发布: (2026年2月6日 GMT+8 13:18)
7 min read
原文: Dev.to

看起来您只提供了来源链接,而没有贴出需要翻译的正文内容。请把要翻译的文本(文章正文)粘贴在这里,我会在保持原有 Markdown 格式和技术术语不变的前提下,将其翻译成简体中文,并保留顶部的来源链接。

介绍

状态管理是前端开发中最棘手的问题之一。随着应用规模的扩大,保持组件之间数据的一致性变得复杂、容易出错且难以调试。Redux 的诞生正是为了解决这个问题,提供一种严格且可预测的架构。

Redux 是一个用于 JavaScript 应用的可预测状态容器。它最常与 React 一起使用,但并不依赖于特定框架,同样可以与 Angular、Vue、Svelte 或原生 JavaScript 配合使用。Redux 管理 UI;它以集中、结构化且可预测的方式管理应用状态。

Redux 解决的问题

  • 属性钻取(在组件层级深处传递数据)
  • 多个真相来源
  • 状态变更不明确
  • 调试困难
  • UI 行为不一致

随着应用的扩展,状态会变得共享、可变且难以追踪。Redux 强制执行规则,消除这些问题。

核心原则

  1. 单一真实来源 – 整个应用的状态存放在一个名为 store 的 JavaScript 对象中。
  2. 只读状态 – 状态不能直接修改;唯一的改变方式是通过分发(dispatch)一个 action。
  3. 纯 reducer – 状态的变更由 reducer 处理,reducer 是纯函数。

这些原则带来的好处包括易于调试、数据集中、时间旅行调试以及状态持久化。

构建块

Redux 由五个核心构建块组成:

  • Store(存储)
  • State(状态)
  • Actions(动作)
  • Reducers(简化器)
  • Middleware(中间件)

Store

store 是 Redux 的核心。它保存整个状态树,提供对状态的访问,并通过 dispatch 进行更新。它还会注册监听器。

import { createStore } from 'redux';

const store = createStore(reducer);

store 暴露三个方法:

  • store.getState() – 返回当前状态
  • store.dispatch(action) – 将动作发送给 reducer
  • store.subscribe(listener) – 为状态变化注册监听器

State

状态是一个普通的 JavaScript 对象。例如:

{
  user: {
    id: 1,
    name: "Alex"
  },
  cart: {
    items: [],
    total: 0
  }
}

重要规则:

  • 状态是 不可变 的。
  • 状态是 可序列化 的。
  • 状态的结构应当是有意且明确的。

Actions

动作是一个普通对象,用来描述发生了什么。

{
  type: "ADD_TODO",
  payload: "Learn Redux"
}

动作的规则:

  • 必须包含 type 属性。
  • 必须是可序列化的。
  • 应该描述事件,而不是包含逻辑。

动作创建函数示例:

function addTodo(text) {
  return {
    type: "ADD_TODO",
    payload: text
  };
}

Reducers

简化器是纯函数,根据先前的状态和动作计算下一个状态。

function todoReducer(state = [], action) {
  switch (action.type) {
    case "ADD_TODO":
      return [...state, action.payload];
    default:
      return state;
  }
}

简化器的规则:

  • 绝不能直接修改状态。
  • 不写异步代码或副作用。
  • 必须返回一个新状态(或未改变的原状态)。

大型应用会使用 combineReducers 按业务域拆分简化器:

import { combineReducers } from 'redux';

const rootReducer = combineReducers({
  user: userReducer,
  cart: cartReducer
});

Middleware

中间件在 dispatch 与简化器之间加入自定义行为。常见用例包括日志、异步请求、错误处理和分析。

Redux 本身是同步的。为处理异步逻辑,thunk 中间件允许分发函数:

store.dispatch((dispatch) => {
  fetchData().then(data => {
    dispatch({ type: "SUCCESS", payload: data });
  });
});

使用中间件的典型流程:

  1. 动作被分发。
  2. 中间件拦截。
  3. 执行异步工作(如果有)。
  4. 真正的动作被分发。
  5. 简化器计算新状态。

单向数据流

Redux 强制执行严格的单向数据流:

UI → Action → Middleware (optional) → Reducer → Store → UI

这种可预测性消除了隐藏的变更、双向数据流和隐式状态变化。每一次状态更改都可以被记录、回放、调试和测试。

何时使用 Redux

Redux 并非所有应用都必须使用。可以在以下情况下考虑使用:

  • 状态在多个组件之间广泛共享。
  • 状态逻辑较为复杂。
  • 调试和可追溯性很重要。
  • 应用规模较大或预计会持续增长。

对于状态主要是局部且更新简单的小型应用,避免使用 Redux。

Redux Toolkit(RTK)

如今,Redux Toolkit 是使用 Redux 的推荐方式。它减少了样板代码,内部使用 Immer 进行不可变更新,强制最佳实践,并默认包含有用的中间件。

使用 RTK 创建 slice 的示例:

import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: "counter",
  initialState: 0,
  reducers: {
    increment: state => state + 1
  }
});

RTK 让 Redux 保持强大,同时避免了通常的复杂性。

常见误解

  • ❌ Redux 只适用于 React – Redux 是一种状态架构,而不是 UI 工具,并且可与任何前端框架或纯 JavaScript 一起使用。
  • ✔ Redux 不是 UI 库 – 它不渲染组件;它仅管理状态。

Conclusion

Redux 是一种状态管理哲学,强调纪律性、可预测性、显式的数据流以及长期可维护性。正确使用时,它的可扩展性优于大多数替代方案,并为复杂应用提供可靠、易于调试且可扩展的状态管理。

Back to Blog

相关文章

阅读更多 »

理解 React 中的 useState

useState 解决了什么问题?在 React 之前,更新屏幕上的内容需要: - 找到 HTML 元素 - 手动更新它 - 确保不…

ReactJS Hook 模式 ~派生状态~

ReactJS Hook 模式 ~Deriving State~ 的封面图片 https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2...

useReducer 与 useState

useState JavaScript const contactName, setContactName = useState''; const contactImage, setContactImage = useStatenull; const contactImageUrl, setContactImageU...