当前位置: 首页 > article >正文

Zustand V5教程:Vanilla Store 与 useStore 使用详解 + 实战 Demo

Zustand 是一个轻量、灵活的状态管理库。自从 Zustand v4 推出 Vanilla Store 后,我们可以更优雅地在组件外(如 API 拦截器、工具函数)访问状态,同时在组件内继续享受响应式的状态订阅。

本教程将通过一个“登录状态管理”示例,讲解:

  • Vanilla Store 和 useStore 的区别
  • 如何在组件外获取状态
  • 如何在组件内响应状态变化
  • 实战完整代码(TypeScript + Zustand + Axios)

🧠 一图理解 Zustand 状态访问方式

场景用法是否响应式适合位置
组件内useStore(...)
或封装的 hook(如 useAuthToken()
✅ 是React 组件
组件外store.getState()
/ store.setState()
❌ 否axios、router、utils 等

🔧 Step 1:定义 Zustand Vanilla Store

// stores/authStore.ts
import { createStore, useStore } from "zustand";
import { persist, createJSONStorage } from "zustand/middleware";
import { immer } from "zustand/middleware/immer";interface AuthState {token: string | null;refreshToken: string | null;userId: string | null;userName: string | null;setToken: (token: string, refreshToken: string) => void;clearToken: () => void;userLogin: (data: {token: string;refreshToken: string;userId: string;userName: string;}) => void;
}export const authStore = createStore<AuthState>()(immer(persist((set) => ({token: null,refreshToken: null,userId: null,userName: null,setToken: (token, refreshToken) => set({ token, refreshToken }),clearToken: () =>set({token: null,refreshToken: null,userId: null,userName: null,}),userLogin: (userData) => {const { token, refreshToken, userId, userName } = userData;set({ token, refreshToken, userId, userName });},}),{name: "auth-storage",storage: createJSONStorage(() => localStorage),partialize: (state) => ({token: state.token,refreshToken: state.refreshToken,userId: state.userId,userName: state.userName,}),}))
);// 自定义 Hook
export const useAuthStore = <T>(selector: (state: AuthState) => T): T =>useStore(authStore, selector);export const useAuthToken = () =>useAuthStore((state) => state.token);export const useAuthUser = () =>useAuthStore((state) => ({userId: state.userId,userName: state.userName,}));export const useAuthActions = () =>useAuthStore((state) => ({login: state.userLogin,logout: state.clearToken,setToken: state.setToken,}));// 外部访问方法
export const getAuthState = () => authStore.getState();
export const setAuthState = authStore.setState;

🚀 Step 2:axios 中使用 token(非组件内)

// utils/axios.ts
import axios from "axios";
import { getAuthState } from "@/stores/authStore";const instance = axios.create({baseURL: "/api",timeout: 10000,
});instance.interceptors.request.use((config) => {const token = getAuthState().token;if (token) {config.headers.Authorization = `Bearer ${token}`;}return config;
});export default instance;

注意:我们没有用 **useAuthStore()**,因为拦截器不是 React 环境,不能使用 Hooks!


🧩 Step 3:React 组件中响应状态

// components/UserProfile.tsx
import React from "react";
import { useAuthUser, useAuthActions } from "@/stores/authStore";const UserProfile = () => {const { userId, userName } = useAuthUser();const { logout } = useAuthActions();return (<div><p>用户:{userName} (ID: {userId})</p><button onClick={logout}>退出登录</button></div>);
};

userNameuserId 发生变化时,组件会自动刷新。


🎯 总结

你要做什么推荐用法
React 组件内使用 tokenuseAuthToken()
React 组件内使用 user 信息useAuthUser()
React 中调用登录/登出方法useAuthActions()
在 axios、工具函数中获取 tokenauthStore.getState().token
或封装的 getAuthState()
在外部设置状态authStore.setState()
或封装的 setAuthState()

相关文章:

Zustand V5教程:Vanilla Store 与 useStore 使用详解 + 实战 Demo

Zustand 是一个轻量、灵活的状态管理库。自从 Zustand v4 推出 Vanilla Store 后&#xff0c;我们可以更优雅地在组件外&#xff08;如 API 拦截器、工具函数&#xff09;访问状态&#xff0c;同时在组件内继续享受响应式的状态订阅。 本教程将通过一个“登录状态管理”示例&a…...

docker 搭建php 开发环境 添加扩展redis、swoole、xdebug(1)

docker-compose搭建lnmp 先决条件 首先需要安装docker 安装docker-compost 1、创建lnmp工作目录 #创建三个目录 mkdir lnmp && cd lnmp mkdir -p nginx/conf php mysql/data lnmp/www#编写nginx 配置文件 nginx/conf/default.conf vim nginx/conf/default.confserv…...

人脸识别技术合规备案最新政策详解

《人脸识别技术应用安全管理办法》将于2025年6月1日正式实施&#xff0c;该办法从技术应用、个人信息保护、技术替代、监管体系四方面构建了人脸识别技术的治理框架&#xff0c;旨在平衡技术发展与安全风险。 一、明确技术应用的边界 公共场所使用限制&#xff1a;仅在“维护公…...

(16)高性能风控系统设计

文章目录 &#x1f680; 高性能风控系统设计&#xff1a;千万级QPS实时风控解决方案TL;DR&#x1f3d7;️ 系统整体架构&#x1f4bb; Java技术栈选型详解1️⃣ 接入层技术选型&#x1f525; 接入层代码示例 2️⃣ 规则引擎层技术选型&#x1f9e0; 规则引擎优化技巧 3️⃣ 数据…...

AStar低代码平台-脚本调用C#方法

修改报工表表单&#xff0c;右键定义弹出菜单&#xff0c;新增一个菜单项&#xff0c;并在点击事件脚本中编写调用脚本。 编译脚本&#xff0c;然后在模块代码里面定义这个方法&#xff1a; public async Task<int> on_call_import(DataRow curRow) {PrintDataRow(cur…...

企业级RAG技术实战指南:从理论到落地的全景解析

前言 在大模型技术日新月异的今天&#xff0c;检索增强生成&#xff08;RAG&#xff09;技术正成为企业突破AI应用瓶颈的关键利器。当传统AI系统还在处理结构化数据的泥潭中挣扎时&#xff0c;RAG技术已经打开了通向非结构化知识海洋的大门。这本《RAG技术实战指南》以独特的工…...

getline()跳过输入

std::getline(cin, s) 第一个参数传递的是输入流&#xff1a;istream(输入流的基类), ifstream, istrstream 的引用&#xff1b; 第二个参数传递的是本地字符串引用&#xff0c;即从输入流读出来的东西要存放的位置。 会跳过getline()的输入 cin >> ch; getline(cin, s…...

【八股战神篇】RabbitMQ高频面试题

简述RabbitMQ五种模式 &#xff1f; 延伸 请介绍一下RabbitMQ的特点 延伸 简述RabbitMQ的发布与订阅模式 延伸 RabbitMQ 如何保证消息不丢失&#xff1f; 延伸 RabbitMQ 如何保证消息有序&#xff1f; 延伸 专栏简介 八股战神篇专栏是基于各平台共上千篇面经&#xf…...

高阶数据结构——红黑树实现

目录 1.红黑树的概念 1.1 红黑树的规则&#xff1a; 1.2 红黑树的效率 2.红黑树的实现 2.1 红黑树的结构 2.2 红黑树的插入 2.2.1 不旋转只变色&#xff08;无论c是p的左还是右&#xff0c;p是g的左还是右&#xff0c;都是一样的变色处理方式&#xff09; 2.2.2 单旋变色…...

互联网大厂Java求职面试:AI与大模型应用集成中的架构难题与解决方案

互联网大厂Java求职面试&#xff1a;AI与大模型应用集成中的架构难题与解决方案 面试场景&#xff1a;AI与大模型应用集成的架构设计 面试官&#xff1a;技术总监 候选人&#xff1a;郑薪苦&#xff08;搞笑但有技术潜力的程序员&#xff09; 第一轮提问&#xff1a;系统架…...

安卓学习笔记-声明式UI

声明式UI Jetpack Compose 是 Google 推出的用于构建 Android UI 的现代化工具包。它采用 声明式编程模型&#xff08;Declarative UI&#xff09;&#xff0c;用 Kotlin 编写&#xff0c;用于替代传统的 XML View 的方式。一句话概括&#xff1a;Jetpack Compose 用 Kotlin…...

AI天气预报进入“大模型时代“:如何用Transformer重构地球大气模拟?

引言:从数值预报到AI大模型的范式变革 传统的天气预报依赖于数值天气预报(NWP, Numerical Weather Prediction),通过求解大气动力学方程(如Navier-Stokes方程)进行物理模拟。然而,NWP计算成本极高,依赖超级计算机,且难以处理小尺度天气现象(如短时强降水)。 近年来…...

本地项目如何设置https(2)——2025-05-19

在配置本地HTTPS时&#xff0c;安装mkcert工具本身是全局操作&#xff08;安装在系统环境&#xff0c;与项目无关&#xff09;&#xff0c;但生成证书时需要进入项目目录操作。以下是具体说明&#xff1a; 安装 mkcert&#xff08;全局操作&#xff09; 安装位置&#xff1a;无…...

数据结构第3章 线性表 (竟成)

目录 第 3 章 线性表 3.1 线性表的基本概念 3.1.1 线性表的定义 3.1.2 线性表的基本操作 3.1.3 线性表的分类 3.1.4 习题精编 3.2 线性表的顺序存储 3.2.1 顺序表的定义 3.2.2 顺序表基本操作的实现 1.顺序表初始化 2.顺序表求表长 3.顺序表按位查找 4.顺序表按值查找 5.顺序表…...

JAVA面试复习知识点

面试中遇到的题目&#xff0c;记录复习&#xff08;持续更新&#xff09; Java基础 1.String的最大长度 https://www.cnblogs.com/wupeixuan/p/12187756.html 2.集合 Collection接口的实现&#xff1a; List接口&#xff1a;ArraryList、LinkedList、Vector Set接口&#xff1a…...

项目中的流程管理之Power相关流程管理

一、低功耗设计架构规划&#xff08;Power Plan&#xff09;   低功耗设计的起点是架构级的电源策略规划&#xff0c;主要包括&#xff1a;   电源域划分   基于功能模块的活跃度划分多电压域&#xff08;Multi-VDD&#xff09;&#xff0c;非关键模块采用低电压&#xf…...

SLOT:测试时样本专属语言模型优化,让大模型推理更精准!

SLOT&#xff1a;测试时样本专属语言模型优化&#xff0c;让大模型推理更精准&#xff01; 大语言模型&#xff08;LLM&#xff09;在复杂指令处理上常显不足&#xff0c;本文提出SLOT方法&#xff0c;通过轻量级测试时优化&#xff0c;让模型更贴合单个提示。实验显示&#x…...

《计算机组成原理》第 10 章 - 控制单元的设计

目录 10.1 组合逻辑设计 10.1.1 组合逻辑控制单元框图 10.1.2 微操作的节拍安排 10.1.3 组合逻辑设计步骤 10.2 微程序设计 10.2.1 微程序设计思想的产生 10.2.2 微程序控制单元框图及工作原理 10.2.3 微指令的编码方式 1. 直接编码&#xff08;水平型&#xff09; 2.…...

【数据结构与算法】模拟

成熟不是为了走向复杂&#xff0c;而是为了抵达天真&#xff1b;不是为了变得深沉&#xff0c;而是为了保持清醒。 前言 这是我自己刷算法题的第五篇博客总结。 上一期笔记是关于前缀和算法&#xff1a; 【数据结构与算法】前缀和-CSDN博客https://blog.csdn.net/hsy1603914691…...

PyTorch入门-torchvision

torchvision torchvision 是 PyTorch 的一个重要扩展库&#xff0c;专门针对计算机视觉任务设计。它提供了丰富的预训练模型、常用数据集、图像变换工具和计算机视觉组件&#xff0c;大大简化了视觉相关深度学习项目的开发流程。 我们可以在Pytorch的官网找到torchvision的文…...

LVS负载均衡群集技术深度解析

第一章 群集技术概述与LVS基础 1.1 群集技术的核心价值与分类 随着互联网应用的复杂化&#xff0c;单台服务器在性能、可靠性、扩展性等方面逐渐成为瓶颈。群集技术&#xff08;Cluster&#xff09;通过整合多台服务器资源&#xff0c;以统一入口对外提供服务&#xff0c;成为…...

18、Python字符串全解析:Unicode支持、三种创建方式与长度计算实战

适合人群&#xff1a;零基础自学者 | 编程小白快速入门 阅读时长&#xff1a;约6分钟 文章目录 一、问题&#xff1a;Python的字符串是什么&#xff1f;1、例子1&#xff1a;多语言支持演示2、例子2&#xff1a;字符串不可变性验证3、答案&#xff1a;&#xff08;1&#xff09…...

5月27日复盘-Transformer介绍

5月27日复盘 二、层归一化 层归一化&#xff0c;Layer Normalization。 Layer Normalizatioh和Batch Normalization都是用来规范化中间特征分布&#xff0c;稳定和加速神经网络训练的&#xff0c;但它们在处理方式、应用场景和结构上有本质区别。 1. 核心区别 特征BatchNo…...

CSV数据处理全指南:从基础到实战

CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔值&#xff09; 是一种简单的文件格式&#xff0c;用于存储和交换表格数据&#xff08;如电子表格或数据库中的记录&#xff09;。其核心特点是用逗号分隔字段&#xff0c;以换行符分隔记录。 CSV 的定义与结构 基本…...

MyBatis-Plus一站式增强组件MyBatis-Plus-kit(更新2.0版本):零Controller也能生成API?

MyBatis-Plus-Kit &#x1f680; MyBatis-Plus-Kit 是基于MyBatis-Plus的增强组件&#xff0c;专注于提升开发效率&#xff0c;支持零侵入、即插即用的能力扩展。它聚焦于 免写 Controller、代码一键生成、通用响应封装 等核心场景&#xff0c;让您只需专注业务建模&#xff0…...

实时数仓flick+clickhouse启动命令

1、启动zookeeper zk.sh start 2、启动DFS&#xff0c;Hadoop集群 start-dfs.sh 3、启动yarn start-yarn.sh 4、启动kafka 启动Kafka集群 bin/kafka-server-start.sh -daemon config/server.properties 查看Kafka topic 列表 bin/kafka-topics.sh --bootstrap-server local…...

【Git】Commit Hash vs Change-Id

文章目录 1、Commit 号2、Change-Id 号3、区别与联系4、实际场景示例5、为什么需要两者&#xff1f;6、总结附录——Gerrit 在 Git 和代码审查工具&#xff08;如 Gerrit&#xff09;中&#xff0c;Commit 号&#xff08;Commit Hash&#xff09; 和 Change-Id 号 是两个不同的…...

Netty学习专栏(六):深度解析Netty核心参数——从参数配置到生产级优化

文章目录 前言一、核心参数全景解析1.1 基础网络层参数1.2 内存管理参数1.3 水位线控制1.4 高级参数与系统级优化 二、生产级优化策略2.1 高并发场景优化2.2 低延迟场景优化 总结 前言 在分布式系统和高并发场景中&#xff0c;Netty作为高性能网络通信框架的核心地位无可替代。…...

服务器磁盘按阵列划分为哪几类

以下是服务器磁盘阵列&#xff08;RAID&#xff09;的详细分类及技术解析&#xff0c;基于现行行业标准与实践应用&#xff1a; 一、主流RAID级别分类 1. ‌RAID 0&#xff08;条带化&#xff09;‌ ‌技术原理‌&#xff1a;数据分块后并行写入多块磁盘&#xff0c;无…...

在WPF中添加动画背景

在WPF中添加动画背景 在WPF中创建动画背景可以大大增强应用程序的视觉效果。以下是几种实现动画背景的方法&#xff1a; 方法1&#xff1a;使用动画ImageBrush&#xff08;图片轮播&#xff09; <Window x:Class"AnimatedBackground.MainWindow"xmlns"htt…...