一些常见的 Redux 和 Zustand 的面试题汇总,后续不断更新。。。

8 阅读8分钟

Redux:

1. Redux 的核心概念是什么?

Redux 核心三件套:

Store -> 状态管理,action -> 描述“发生了什么”,reducer -> 如何修改 state

2. Redux 工作流程

组件 dispatch action

store 接收 action

reducer 根据 action.type 修改 state

返回新的 state

组件重新渲染

3. Redux 为什么是单向数据流?

Redux 之所以是单向数据流,是因为它强制规定状态只能通过 dispatch action → reducer → store update 的固定流程修改,从而让状态变化可预测、可追踪、易调试。

这样设计的核心目的,是避免组件随意修改共享状态,因为大型项目里:状态来源会越来越复杂,多组件共享状态,异步逻辑越来越多

所以单向数据量解决的痛点是:所有状态修改都有记录,所有修改路径唯,DevTools 可追踪

流程:

View
↓ dispatch
Action

Reducer

Store

View 更新

4. Redux 为什么 reducer 必须是纯函数?

因为 Redux 需要保证相同输入一定得到相同输出,这样状态变化才可预测,同时方便调试、时间旅行和状态回溯。

需要注意的是,对于纯函数要求的要求是:不修改外部变量,不产生副作用,相同输入得到相同输出

只有这样,才能做到:正确比较 state,实现 time-travel,实现状态快照,保证 reducer 可测试

5. Redux 为什么强调 immutable(不可变数据)?

因为 Redux 是通过对象引用变化判断 state 是否更新的,如果直接修改原对象,会导致 React 无法正确检测更新。

6. Redux middleware 是什么?

Redux middleware 本质上是对 dispatch 的增强,可以在 action 到达 reducer 之前进行拦截、扩展和异步处理。

流程:

dispatch(action)

middleware

reducer

常见用途:异步请求,日志打印,权限校验,错误处理

7. redux-thunk 为什么能处理异步?

因为 redux-thunk 允许 dispatch 一个函数,而不是普通对象,从而把异步逻辑放进函数里执行。

8. Redux Toolkit 为什么流行?

Redux Toolkit 解决了传统 Redux 样板代码过多、配置复杂的问题,让 Redux 更简单、更现代化。

核心优化:

RTK:自动生成 action,内置 thunk,内置 DevTools,集成 Immer,简化 store 配置

9. RTK 为什么能直接修改 state?

因为 Redux Toolkit 内部使用了 Immer,它会通过 Proxy 追踪修改,最终生成不可变的新对象。

10. selector 为什么能优化性能?

因为 selector 可以让组件只订阅自己需要的 state,从而减少不必要的重新渲染。

11. Redux 为什么适合大型项目?

因为 Redux 具有强约束、单向数据流和成熟中间件生态,在多人协作和复杂状态场景下更容易维护。

首先,Redux 优势是规范统一,状态变化可追踪,DevTools 强,middleware 丰富,团队协作稳定

12. Redux 的 combineReducers 是怎么实现的?

combineReducers 返回一个总 reducer,它会遍历所有子 reducer,依次调用并收集结果。

只要任意子 reducer 返回的对象引用变了,整个 state 就会被标记为变化。

13. connect 是如何实现性能优化的?

connect 是一个高阶组件,它会:

  1. 订阅 Store 变化

  2. 执行 mapStateToProps 和 mapDispatchToProps

  3. 浅比较新旧 props,只有变化时才重新渲染组件

优化方式:

内置 shouldComponentUpdate 浅比较

支持 mergeProps 自定义合并逻辑

搭配 reselect 避免重复计算

14. Redux 的状态更新一定是同步的吗?异步如何处理?

Redux 原生只支持同步更新。异步需要通过中间件(如 redux-thunk、redux-saga)来实现。

对比:

方式特点
无中间件dispatch 必须接收普通 action 对象
redux-thunkdispatch 可接收函数,异步逻辑写在函数内
redux-saga用 Generator 管理复杂异步流程

15. 为什么 Redux 不推荐将 Class 实例、函数等放入 Store?

  • Redux 依赖序列化实现时间旅行、状态持久化、SSR

  • 函数和实例无法被 JSON.stringify() 序列化

  • devtools 难以正确记录和回溯

16. Redux + Context API 有什么区别?什么时候用 Context 替代 Redux?

对比项Context APIRedux
设计目标解决 props drilling可预测状态管理
性能无内置优化,值变化会导致所有消费者重渲染通过 selector 精确订阅
中间件❌ 不支持✅ 丰富生态
DevTools❌ 弱✅ 强大
适用场景主题、语言、用户信息等低频更新复杂交互、频繁更新的全局状态

结论:  Context 适合低频、浅层状态共享;Redux 适合频繁更新、逻辑复杂的场景。

17. Redux 和 MobX 的核心区别是什么?

对比项ReduxMobX
范式函数式 + 不可变响应式 + 可变
学习曲线陡峭平缓
样板代码
调试devtools 强较弱
适用场景大型、多人协作中小型、快速迭代

Redux 约定大于配置,MobX 配置大于约定。Redux 更严格适合团队协作,MobX 更灵活适合个人/小团队。

18. 使用 Redux 时遇到过哪些性能问题?如何解决?

常见问题:

  1. 不必要的重新渲染 → 使用 reselect + 精细化 selector

  2. State 过于庞大 → 拆分为多个 reducer + 按需加载

  3. 频繁 dispatch 导致卡顿 → 批量更新(redux-batched-actions)

  4. 深层对象更新性能差 → 使用 Immer 或 normalizr 扁平化

19. 刷新页面后 Redux 状态丢失怎么办?如何持久化?

原因:  Redux 状态存在内存中,刷新页面 JS 重新执行,Store 重置。

解决方案:

  1. 使用 redux-persist 将状态同步到 localStorage / sessionStorage

  2. 或 SSR 时将初始状态注入 HTML

20. 如何在 Redux 中处理嵌套数据更新?

核心答案:  避免直接修改嵌套数据,使用:

  • 扩展运算符{ ...state, nested: { ...state.nested, key: newValue } }

  • Immerdraft.nested.key = newValue(RTK 已内置)

  • normalizr:扁平化数据结构,避免深层嵌套

Zustand:

1. Zustand 为什么火?

因为 Zustand API 非常简单,没有 Redux 那么重,同时还能实现高性能的精准状态订阅。

2. Zustand 为什么不需要 Provider?

因为 Zustand 的 store 独立于 React,它不是基于 Context 实现的,而是基于发布订阅模式。

补充:

Context:Provider -> Consumer

Zustand:store 独立存在,组件直接订阅

3. Zustand 为什么性能更好?

因为 Zustand 支持精准订阅,只有依赖某个 state 的组件才会重新渲染,而不是整个组件树更新。

对比:

Context:

value 变化
↓
所有 consumer 重新渲染

Zustand:

count 变化
↓
只有使用 count 的组件更新

4. Zustand 的核心原理是什么?

Zustand 的核心原理是发布订阅模式,通过 listeners 监听 state 变化,然后通知对应组件更新。

补充

setState
↓
通知 listeners
↓
组件重新渲染

14. Zustand 为什么适合中小项目?

因为 Zustand 学习成本低、开发效率高、代码量少,非常适合快速开发和轻量级状态管理。

15. Zustand 有什么缺点?

Zustand 最大的问题是约束较少,如果项目规模变大,容易导致 store 混乱。

补充

因为:

  • 没有 reducer 规范

  • 没有 action 约束

  • 逻辑容易随意堆积

所以大型项目需要:

  • store 模块化

  • 命名规范

  • 状态拆分

16. Redux 和 Zustand 的区别?

Redux 更偏向规范化和大型项目管理,而 Zustand 更偏向轻量化和开发效率。

ReduxZustand
强约束灵活
reducer无 reducer
样板代码多API 简单
生态成熟更轻量
适合大型项目适合中小项目

17. 什么场景用 Redux?

当项目状态复杂、多人协作、需要强规范和复杂中间件时,我会优先选择 Redux。

18. 什么场景用 Zustand?

当项目追求开发效率、状态逻辑不复杂,或者主要是 UI 状态管理时,我会优先选择 Zustand。

19. Zustand 是如何实现精准订阅的?

Zustand 内部通过selector 函数 + 浅比较决定是否触发更新。

关键点:

  • 没有 selector 时订阅整个 store(state => state

  • 每次 state 变化都会执行 selector,比较结果决定是否重渲染

  • 这就是 Zustand 性能优于 Context 的根本原因

20. Zustand 的 set 函数是如何工作的?支持哪些写法?

set 是 Zustand 提供的唯一修改状态的方法,支持三种写法:

写法示例适用场景
对象直接合并set({ count: 1 })简单更新
函数式更新set(state => ({ count: state.count + 1 }))依赖当前值
合并 + 替换set({ count: 1 }, true)第二个参数为 true 时完全替换(非合并)

21. Zustand 如何处理异步操作?

Zustand 直接支持异步,不需要额外中间件。

与 Redux 对比:  Redux 需要 thunk/saga,Zustand 原生支持,更简单直接。

22. Zustand 的中间件机制是什么?

Zustand 中间件通过高阶函数包装增强 store 能力。

中间件作用用法
devtools连接 Redux DevToolscreate(devtools(myStore))
persist持久化到 localStoragecreate(persist(myStore, { name: 'storage-key' }))
immer支持可变写法create(immer(myStore))
subscribeWithSelector增强订阅功能create(subscribeWithSelector(myStore))

23. Zustand 如何在 React 外部使用?

Zustand store 独立于 React,可以在任何地方使用。

对比 Redux:  Redux 也可以在外部使用,但 Zustand 的 createStore API 更直观。

24. Zustand 如何实现 Store 之间相互调用?

使用 create 提供的 get 参数,或在创建后通过 useStore.getState() 获取。

25. Zustand 的 Slice 模式如何实现代码分割?

Slice 模式将大 store 拆分为多个小模块,便于维护和复用。