首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Redux真的该换了吗?2025年React状态管理的残酷真相

Redux真的该换了吗?2025年React状态管理的残酷真相

作者头像
前端达人
发布2025-11-20 08:39:11
发布2025-11-20 08:39:11
470
举报
文章被收录于专栏:前端达人前端达人

你是否还在为庞大的Redux项目维护而头疼?或者正在新项目中纠结应该选择Zustand还是Redux?本文将彻底拆解2025年React状态管理的真实困境——答案可能会颠覆你的认知。

第一个残酷真相:90%的项目其实不需要Redux

先问你一个问题:你项目中的Redux代码到底在干什么?

很多开发者会发现,当他们开始从Redux迁移时,会惊讶地发现——整个Redux的样板代码、action、reducer、中间件、selectors……其实可以被三个不同的、更专业的工具完全替代,而且效果更好。这听起来有点荒诞,但这正是2025年的现实。

问题的根源:大一统思维已经过时

还记得那个时代吗?当所有的"状态"都被塞进Redux store里——API响应数据、URL参数、modal打开状态、表单临时值……这种大一统的思维在2010年代是标准做法。但这也是Redux最臃肿的地方。

Redux Toolkit的出现本身就能说明问题——如果Redux真的设计合理,为什么还要发明一个toolkit来"简化"它?这就像说一个正确的设计需要修补一样。

真相二:状态应该按"场景"分类而不是"位置"

让我们把应用的"状态"重新分类。关键不是问"这个状态放在哪里",而是问"这个状态是什么性质的"。性质不同,处理方案完全不同。

1. 远程状态(Remote State):大头来了

这才是你Redux代码的90%所在。

想象一个典型场景:用户打开商城页面,需要加载商品列表。这看起来简单,但实际上涉及:

  • 加载状态 - 页面转圈还是展示骨架屏?
  • 💥 错误处理 - 接口超时了怎么显示?
  • 🔄 请求去重 - 两个组件同时请求同一个商品列表,能只发一次请求吗?
  • 📦 缓存策略 - 用户从详情页返回列表页,数据是否需要重新加载?
  • 并行加载 - 列表加载中能同时预加载详情页数据吗?
  • 🎯 乐观更新 - 用户点击收藏时,UI马上变心形,万一失败再改回去?
  • 🌪️ 竞态条件 - 用户快速搜索时,旧请求的结果不应该覆盖新搜索结果

所有的复杂性,Redux原生无法优雅地处理。你需要写中间件、自定义逻辑、手写缓存层……而现在,有更好的方案。

推荐方案:TanStack Query

代码语言:javascript
复制
function ProductList() {
const { isPending, error, data } = useQuery({
    queryKey: ['products', category],  // 关键字自动去重
    queryFn: () => fetchProducts(category),
    staleTime: 1000 * 60 * 5,  // 5分钟内的数据被认为是"新鲜"的
  });

if (isPending) return<SkeletonLoader />;
if (error) return<ErrorBoundary error={error} />;

return<ProductGrid data={data} />;
}

这一个hook解决了上面列出的所有问题。没有action、没有reducer、没有中间件。试试从Redux迁移到TanStack Query,你会流泪——因为消失的代码太多了。

官方数据显示:从Redux迁移到TanStack Query,平均消除80%的状态管理相关代码。

2. URL状态(Query Params):被遗忘的金库

有多少次,你手动在Redux里同步URL参数?

代码语言:javascript
复制
// Redux的"正确做法":
const [filter, setFilter] = useState('all');
// 然后你需要在某个地方写:
useEffect(() => {
  history.push(`?filter=${filter}`);
}, [filter]);
// 然后还要在另一个地方写:
useEffect(() => {
  const params = new URLSearchParams(location.search);
  setFilter(params.get('filter') || 'all');
}, [location.search]);

这是Redux开发者常犯的"主动找麻烦"。

更聪明的做法:使用nuqs

代码语言:javascript
复制
import { useQueryState } from 'nuqs';

function ProductFilter() {
  const [filter, setFilter] = useQueryState('filter', { defaultValue: 'all' });
  
  return (
    <div>
      <button onClick={() => setFilter('sale')}>特价商品</button>
      {/* URL自动变成 ?filter=sale,刷新也不丢失状态 */}
    </div>
  );
}

URL状态本质上是持久化状态,不应该在内存store里维护。这不仅更简洁,用户还可以复制链接分享当前的筛选条件。

3. 本地状态(Local Component State):99%的开发者过度使用Redux

一个modal的打开/关闭状态需要放在Redux里吗?一个表单的输入框值需要全局管理吗?

答案是:绝对不需要。

代码语言:javascript
复制
function ProductModal() {
  // 这就够了,不需要Redux
  const [isOpen, setIsOpen] = useState(false);
  const [formData, setFormData] = useState({ name: '', price: '' });
  
  return (
    // ...组件内容
  );
}

使用Redux来管理这种状态,就像用大炮打蚊子。但中国开发者在企业项目中经常看到这种情况——整个应用的Redux store里充满了这种"本来不应该在这里"的状态。

4. 真正的共享状态(Shared Component State):这才是Redux的战场

现在我们来到了真正需要Redux的场景——多个无关的组件需要共享同一个状态。

比如:

  • 用户的登录信息(header、sidebar、user menu都需要)
  • 主题设置(全局深色/浅色模式)
  • 应用配置(所有功能模块都可能依赖)
  • 购物车(header显示商品数,详情页加入购物车)

这是真正需要全局状态管理的地方,通常也不会特别复杂。

第三个真相:Zustand正在悄悄赢

如果你承认确实需要共享状态,那么下一个问题是:用什么库?

让我们按照硬指标来评测当前最流行的几个库:

评测维度1:简洁性

这很重要,因为越简洁的库,当维护者消失时,迁移成本越低。

Redux 👎 - 臭名昭著的样板代码。你需要学习action types、action creators、reducer逻辑、中间件……

代码语言:javascript
复制
// Redux的繁琐
const SET_USER = 'SET_USER';
const setUser = (user) => ({ type: SET_USER, payload: user });
const userReducer = (state = null, action) => {
  switch(action.type) {
    case SET_USER: return action.payload;
    default: return state;
  }
};

Redux Toolkit 😐 - 改善了,但依然不够简洁。你还是要理解slices、thunks这些概念。

Zustand 🎉 - 赢家。两行代码就能上手:

代码语言:javascript
复制
import create from'zustand';

const useUserStore = create((set) => ({
user: null,
setUser: (user) =>set({ user }),
}));

// 使用
function UserProfile() {
const user = useUserStore((state) => state.user);
return<div>{user?.name}</div>;
}

MobX 👎 - "Observables"和"reactive programming"——对React开发者来说是陌生的概念。

Jotai 👎 - 引入了"atoms"这种抽象概念,虽然强大但学习曲线陡峭。

XState 👎 - "State machines"、"actors"、"events"——这东西的学习成本简直是天文数字。除非你在做Figma这样的复杂应用,否则没必要。

评测维度2:性能(避免不必要的重渲染)

共享状态库最常见的问题是:修改了一个小状态,结果所有使用该store的组件都重新渲染。

Redux & Redux Toolkit

✅ - 通过selectors能避免,但需要手动写。Zustand

✅ - 开箱即用,自动订阅你访问的属性。

代码语言:javascript
复制
// 只有当user变化时才会重渲染,theme变化时不会触发
const user = useUserStore((state) => state.user);

评测维度3:生态和长期支持

Redux - 有官方支持,但逐渐在衰退。看看最新的Next.js或Fresh app模板,都没有预设Redux。

Zustand - 由主流开源社区维护(pmndrs),活跃度高。作者同时也是Jotai的维护者,说明这是个可信赖的团队。

TanStack Query - 更新频繁,有赞助商支持,生态健康。

第四个真相:2025年的最佳实践组合

如果你现在要启动一个新项目,完全摆脱遗留包袱,应该这样组织你的状态管理:

代码语言:javascript
复制
你的项目状态树
├── 远程数据(API来的数据)
│   └── TanStack Query 处理
├── URL状态(查询参数、页面路由)
│   └── nuqs 处理
├── 本地组件状态(modal、表单输入)
│   └── useState / useReducer 处理
└── 全局共享状态(用户信息、主题)
    └── Zustand 处理

这个组合的威力在于:

  • 每个工具都专注于一个问题,因此都做得很好
  • 当任何一个工具出问题时,替换成本最低(因为隔离了)
  • 总代码量比Redux方案少70-90%
  • 性能更好(精细化订阅)
  • 新开发者上手速度快10倍

实战示例:电商商品详情页

代码语言:javascript
复制
import { useQuery } from'@tanstack/react-query';
import { useQueryState } from'nuqs';
import { useUserStore } from'@/store/userStore';

exportfunction ProductDetail({ productId }) {
// 远程状态:从API加载商品数据
const { data: product, isPending } = useQuery({
    queryKey: ['product', productId],
    queryFn: () => fetch(`/api/products/${productId}`).then(r => r.json()),
  });

// URL状态:收藏/对比的商品ID存在URL里
const [compareIds, setCompareIds] = useQueryState('compare', {
    defaultValue: '',
  });

// 本地状态:这个组件内的切换逻辑
const [selectedTab, setSelectedTab] = useState('detail');
const [reviewSort, setReviewSort] = useState('newest');

// 全局共享状态:用户的收藏、购物车等
const { addToCart, addToWishlist } = useUserStore();

if (isPending) return<Skeleton />;

return (
    <div>
      <ProductImages images={product.images} />
      
      <div>
        <h1>{product.name}</h1>
        <Price>{product.price}</Price>
        
        <button onClick={() => addToCart(product)}>
          加入购物车
        </button>
        
        <button onClick={() => addToWishlist(product)}>
          收藏
        </button>
      </div>

      <Tabs activeTab={selectedTab} onChange={setSelectedTab}>
        <Tab label="商品详情">{/* 商品信息 */}</Tab>
        <Tab label="用户评论">
          <SortButton 
            value={reviewSort} 
            onChange={setReviewSort} 
          />
          {/* 评论列表 */}
        </Tab>
      </Tabs>
    </div>
  );
}

看这个例子,我们没有写一行Redux代码,但处理了:

  • ✅ API数据加载和缓存
  • ✅ 错误处理和加载态
  • ✅ URL同步(compare参数可以复制链接分享)
  • ✅ 组件内部UI切换状态
  • ✅ 全局用户数据
  • ✅ 购物车和收藏逻辑

常见问题解答

Q: 那Redux Toolkit是不是完全没用了?

不是。如果你在一个大型企业应用中,需要高度结构化和一致的代码规范(比如金融系统),Redux Toolkit的"意见强硬"反而是优势。它的Redux DevTools调试体验也无与伦比。但对于95%的应用来说,确实过度工程化了。

Q: Zustand能替代Redux吗?

对于共享状态的需求,是的。但Zustand是"随意型"的,这对小团队很好,对大团队可能造成代码风格混乱。所以选择时要考虑团队规模。

Q: 那我现在项目的Redux代码怎么办?

分阶段迁移:

  1. 新功能不用Redux,改用TanStack Query + Zustand
  2. 现有功能逐个抽离:远程数据部分→TanStack Query,URL参数→nuqs,其余部分→Zustand
  3. 最后Redux可以完全删除或只保留一个小全局store

Q: 小项目有必要用TanStack Query吗?

严格来说没必要。但一旦项目涉及任何复杂的API逻辑(缓存、重试、去重),TanStack Query立刻让你省掉几十行手写逻辑。性价比极高。

总结:2026年的理性选择

不要问"用什么状态管理库"。 应该问"我有什么类型的状态需要管理,每种类型最合适的工具是什么"。

这个转变可能看起来微妙,但它能彻底改变你写代码的方式:

状态类型

对应工具

Redux时代

改进

远程数据

TanStack Query

50%代码

95%代码删除

URL参数

nuqs

手动同步

自动处理

本地状态

useState

放在Redux

就用本地state

共享状态

Zustand

Redux

少写70%代码

选择这个方案意味着:

  • 👍 代码量减少90%
  • 👍 性能提升(精细化订阅)
  • 👍 新手上手快(每个工具都很简单)
  • 👍 debug更容易(关系清晰)
  • 👍 迁移成本低(工具单一职责)

这不是什么"银弹",但这是2026年React生态发展的必然结果。大一统的做法已经过时了。

最后的话

如果你还在新项目中选择Redux,请问自己一个诚实的问题:是因为技术决定,还是因为"之前一直都这么用"?如果是后者,也许是时候尝试一下新的思路了。

下次在团队会议上提出这个观点时,你会发现很多人都有同样的想法——他们只是在等有人先挑战"Redux是标配"这个观念。

在中文开发者社区中,这个转变来得稍晚一些(因为很多教程还在教Redux),但趋势是确定的。现在是抓住这个机会的好时机。

相关资源

  • TanStack Query 官方文档
  • Zustand Github:
  • nuqs 官方文档
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-10-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一个残酷真相:90%的项目其实不需要Redux
    • 问题的根源:大一统思维已经过时
  • 真相二:状态应该按"场景"分类而不是"位置"
    • 1. 远程状态(Remote State):大头来了
    • 2. URL状态(Query Params):被遗忘的金库
    • 3. 本地状态(Local Component State):99%的开发者过度使用Redux
    • 4. 真正的共享状态(Shared Component State):这才是Redux的战场
  • 第三个真相:Zustand正在悄悄赢
    • 评测维度1:简洁性
    • 评测维度2:性能(避免不必要的重渲染)
    • 评测维度3:生态和长期支持
  • 第四个真相:2025年的最佳实践组合
    • 实战示例:电商商品详情页
  • 常见问题解答
    • Q: 那Redux Toolkit是不是完全没用了?
    • Q: Zustand能替代Redux吗?
    • Q: 那我现在项目的Redux代码怎么办?
    • Q: 小项目有必要用TanStack Query吗?
  • 总结:2026年的理性选择
    • 最后的话
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档