Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Redux

Redux 核心概念

1. 核心三大件:数据、指令与处理器

概念面试金句(定义)大白话理解
Store保存程序所有状态的单一实体,是唯一的真理来源。整个公司的“中央仓库”。
StateStore 中存储的具体数据,通常是一个大的 JSON 对象。仓库里货架上的“货物清单”。
Action描述“发生了什么”的普通对象。必须包含 type,可选 payload一张“出库单”:type 是操作名称,payload 是具体包裹。

2. 核心逻辑:Reducer 与 Dispatch

Reducer (纯函数)

这是面试官最喜欢问的地方。

  1. 不得修改参数(不可变性)。

  2. 不得执行副作用(禁止 API 请求、路由跳转)。

  3. 不得调用非纯函数(禁止 Date.now()Math.random())。

面试提醒:为什么要纯函数?为了可预测性和时间旅行调试(Time Travel Debugging)。

Dispatch & Subscribe

3. 底层脉络:单向数据流 (One-way Data Flow)

这是 Redux 的灵魂。面试时如果能边画图边描述这个闭环,基本稳了:

  1. Trigger (View):用户点击按钮,产生一个意图。

  2. Dispatch (Action):调用 store.dispatch({ type: 'ADD_TODO', payload: '学习Redux' })

  3. Execute (Reducer):Store 自动调用 Reducer,传入当前 State 和这个 Action。Reducer 返回全新的 State。

  4. Update (Store):Store 用新 State 替换旧 State,并触发 Subscribe。

  5. Re-render (View):UI 组件感知到 State 变化,获取新数据并重新渲染。

面试突击小贴士

Redux Toolkit

1. configureStore:开箱即用的指挥中心

在传统 Redux 中,你需要手动组合 combineReducers、应用 applyMiddleware、配置 DevTools

  1. 自动合并:传入 reducer 对象,它会自动调用 combineReducers

  2. 内置中间件:默认引入了 redux-thunk(处理异步)和检查常规错误的中间件(如:检测是否在 Reducer 中直接修改了 State)。

  3. 开发工具:自动开启 Redux DevTools 扩展支持。

2. createSlice:Reducer 与 Action 的“合体”

这是 RTK 的灵魂,彻底解决了“样板代码”繁琐的问题。

3. createAsyncThunk:异步请求的标准化

以前写异步要手写 REQUEST_STARTSUCCESSFAILURE 三个常量,现在 RTK 帮你管。

  1. pending:请求中(通常在这里设置 loading = true)。

  2. fulfilled:请求成功(拿到 payload 更新数据)。

  3. rejected:请求失败(处理 error)。

4. 高阶加分项:性能与扩展

createEntityAdapter (规范化数据)

Listener Middleware

⚡️ 避坑指南(面试常考)

  1. 问:RTK 允许直接修改 State 吗?

  1. 问:为什么还要用 extraReducers

这一部分是面试官考察你“实战经验”的分水岭。如果说 Redux 是大脑,React-Redux 就是神经系统。

React-Redux 集成

1. 连接层:Provider 与 Hooks

Provider:全局注入

useSelectoruseDispatch

2. 性能优化:Selector 的艺术

这是高频考点,核心围绕 “避免无谓重渲染”。

为什么 Selector 要尽量小?

如果你写 const state = useSelector(state => state),那么 Store 中任何细微的变化都会导致该组件重渲染。

避免返回“新对象”

如果在 useSelector 里写了如下代码,会导致组件每次 Action 派发时都重渲染(即使数据没变):

// ❌ 错误示范:每次都返回一个新数组引用
const userIds = useSelector((state) => state.users.map((u) => u.id));

Memoization (Reselect)

createSelector 会缓存输入和输出。只有当输入参数(依赖的 State)发生变化时,它才会重新计算。

3. State 结构设计(架构思维)

扁平化与规范化 (Normalization)

面试官可能会问:“如果你的数据嵌套了三层,怎么更新最快?”

  1. 更新快:修改某个 ID 的数据不影响其他 ID 的引用。

  2. 查询快:O(1)O(1) 时间复杂度直接定位数据。

  3. 减少渲染:列表组件只传 ID 给子组件,子组件根据 ID 自行订阅,避免整个列表重绘。

⚡️ 面试实战 Q&A

Q: useSelector 是如何判断数据是否变化的? A: 默认使用 === 严格相等检查。如果返回的是对象或数组,即便内容一样但引用换了,也会触发渲染。如果非要返回新对象,可以使用 shallowEqual 作为 useSelector 的第二个参数。

Q: 如果一个页面有海量数据,怎么优化 Redux 性能? A: 1. 使用 createEntityAdapter 规范化数据。2. 使用 createSelector 进行记忆化查询。3. 确保 useSelector 的粒度足够小。4. 在父组件只传递 ID,由子组件独立连接 Store。

这是面试中的“压轴题”。很多候选人会说“Redux 功能更强”,但这太笼统。你需要从数据流向、性能优化、调试工具、适用场景四个维度来精准打击。

Redux vs. Context API

维度Context APIRedux (RTK)
定位依赖注入工具。状态管理框架。
数据流简单的“提供者-消费者”模式。严格的“Action-Reducer-Store”单向流。
性能瓶颈: Provider 值变化,所有消费组件强制重渲染。优势: useSelector 实现了原子级订阅,只有数据变化才重绘。
调试依赖 React DevTools,难以追踪历史变化。神器: Redux DevTools 支持“时间旅行”、状态快照。
异步/中间件需配合 useEffect 或第三方库,无标准。完善的中间件机制(Thunk, Saga, Listeners)。

1. 核心差异:重渲染机制(面试高频)

这是面试官最想听到的技术细节:

2. 什么时候用 Context?什么时候用 Redux?

场景 A:使用 Context API

场景 B:使用 Redux (RTK)

3. 常见误区:有了 Hooks 还需要 Redux 吗?

面试官问: “useReducer + useContext 不就是 Redux 吗?” 你的回答: “它们确实能模拟 Redux 的模式,但它们不是 Redux 的替代品。

  1. 缺少中间件:useReducer 没法直接处理异步逻辑。

  2. 性能短板:Context 的全量渲染问题在大型应用中是致命的。

  3. 开发体验:Redux 拥有极其强大的插件生态(如持久化缓存 redux-persist)和 DevTools 调试能力,这是原生 Hooks 组合无法比拟的。”