从 Pinia 到 Zustand:我在 React 里复刻了一套用户状态管理

我是小ao,一名大二学生,正在用 React + TypeScript 开发一个名为"面试克星"的 AI 面试准备平台。在此之前,我用 Vue 3 + Pinia 独立完成过一个全栈论坛项目。切换到 React 技术栈后,我遇到的第一个需要"翻译"的概念就是状态管理。

为什么要用状态管理库?

在"面试克星"里,用户登录后,导航栏需要显示用户名,个人主页需要展示和编辑用户资料,路由守卫需要判断登录状态。如果只用组件内部的 useState,这些数据会在组件间传递得乱七八糟。我需要一个全局的、能让所有组件共享的用户状态中心。

在 Vue 里我有 Pinia,在 React 里我选了 Zustand------它轻量、API 简单,而且和 Pinia 的心智模型非常接近。

Zustand vs Pinia:核心概念对照

概念 Pinia (Vue) Zustand (React)
创建 Store defineStore('auth', { state, actions }) create<State>((set) => ({ ... }))
读取状态 const auth = useAuthStore() const user = useUserStore((s) => s.user)
修改状态 直接修改 this.user = xxx 调用 set({ user: xxx }) 传入新状态
异步操作 actions 里写 async 函数 在 Store 内部直接写 async 函数

最大的差异在于状态的更新方式。Pinia 借助 Vue 的响应式系统,你可以直接修改状态(像改普通对象一样)。Zustand 则遵循 React 的不可变数据原则,你必须通过 set 返回一个新的状态对象。

我设计的 useUserStore

我的 Store 需要管理用户信息、JWT Token、登录状态,并提供登录、注册、退出、更新信息的方法。在用 TypeScript 之后,我发现必须先定义一个 interface,把数据和方法签名提前写好。这比 JS 版本的 Pinia 多了一道工序,但它成了我 Store 的自文档。

typescript 复制代码
interface UserState {
  user: { _id: string; username: string; email: string; ... } | null;
  token: string | null;
  isLogin: boolean;
  login: (email: string, password: string) => Promise<void>;
  register: (email: string, password: string) => Promise<void>;
  loginOut: () => void;
  updateUser: (fields: Partial<...>) => Promise<void>;
}

初始化时,我会从 localStorage 读取 token,如果存在就将 isLogin 设为 true。这样刷新页面后,登录状态不会丢失。

login 方法通过 axios 向后端发送请求,拿到 tokenuser 后,用 set({ user, token, isLogin: true }) 一次性更新 Store。register 同理,成功后只更新 user,因为注册后不自动登录。

updateUser 是我在个人主页实现内联编辑时加的。用户修改年龄、性别等字段后,我会先调后端 PUT /api/users/me 接口,成功后再用 set 更新本地 Store。这保证了前端展示与数据库同步。

那一层 interface,是负担还是助手?

刚开始写 TS 时,我觉得每个 Store 都要写一个长长的接口很麻烦。后来有一次,我在组件里不小心写错了状态名(user.username 打成了 user.userName),TypeScript 立刻在编辑器里划了红线。我突然明白了------这层 interface 不是负担,它是在我出错之前就帮我揪出 bug 的"安全网"。

从 Pinia 到 Zustand,换的是框架,不变的是对"集中管理状态、驱动视图更新"这一模式的理解。真正花时间的,从来不是学习某个库的 API,而是理解"状态管理"本身。

相关推荐
Old Uncle Tom37 分钟前
银行用户画像 -- 金融目标与需求意图
前端·人工智能·金融
IT_陈寒43 分钟前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
东方小月43 分钟前
从0开发一个 Coding Agent(一):前言
前端·人工智能·typescript
恋猫de小郭44 分钟前
Flutter 全新真 3D 实现,用 flutter_scene 能开发一个「我的世界」
android·前端·flutter
ji_shuke1 小时前
远程排查 Web 系统问题:如何导出 HAR 文件协助定位
前端·问题排查
程序员爱钓鱼2 小时前
Rust String 与 &str 详解:字符串所有权、借用与转换
前端·后端·rust
码农学院2 小时前
GEO与SEO协同:从传统搜索到生成式搜索的平滑迁移路径
服务器·前端·python
咩咩啃树皮10 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
阳光是sunny10 小时前
LangGraph中的Reducer是什么
前端·人工智能·后端