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

【React】状态管理之Zustand


鑫宝Code

🌈个人主页: 鑫宝Code
🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础
💫个人格言: "如无必要,勿增实体"


文章目录

  • 状态管理之Zustand
    • 引言
    • 1. Zustand 的核心特点
      • 1.1 简单直观的 API
      • 1.2 无需 Provider
    • 2. 高级特性与用法
      • 2.1 异步操作处理
      • 2.2 中间件支持
      • 2.3 状态切片(Slices)
    • 3. 性能优化
      • 3.1 选择性订阅
      • 3.2 浅比较
    • 4. 实际应用场景
      • 4.1 表单状态管理
      • 4.2 认证状态管理
    • 5. 最佳实践
      • 5.1 Store 组织
      • 5.2 TypeScript 集成
    • 总结

状态管理之Zustand

在这里插入图片描述

引言

Zustand 是一个轻量级的状态管理库,以其简单、灵活和高性能的特点在 React 社区中快速崛起。本文将深入探讨 Zustand 的核心概念、使用方法和最佳实践。

1. Zustand 的核心特点

1.1 简单直观的 API

Zustand 采用极简的 API 设计,创建 store 非常简单:

import create from 'zustand'interface BearStore {bears: numberincrease: () => voiddecrease: () => void
}const useStore = create<BearStore>((set) => ({bears: 0,increase: () => set((state) => ({ bears: state.bears + 1 })),decrease: () => set((state) => ({ bears: state.bears - 1 }))
}))

1.2 无需 Provider

与 Redux 和 Context API 不同,Zustand 不需要 Provider 包裹:

function BearCounter() {const bears = useStore((state) => state.bears)return <h1>{bears} around here...</h1>
}function Controls() {const increase = useStore((state) => state.increase)const decrease = useStore((state) => state.decrease)return (<div><button onClick={increase}>+</button><button onClick={decrease}>-</button></div>)
}

2. 高级特性与用法

在这里插入图片描述

2.1 异步操作处理

interface TodoStore {todos: Todo[]loading: booleanfetchTodos: () => Promise<void>
}const useTodoStore = create<TodoStore>((set) => ({todos: [],loading: false,fetchTodos: async () => {set({ loading: true })try {const response = await fetch('https://api.example.com/todos')const todos = await response.json()set({ todos, loading: false })} catch (error) {set({ loading: false })console.error(error)}}
}))

2.2 中间件支持

Zustand 提供了强大的中间件支持:

import { persist, devtools } from 'zustand/middleware'const useStore = create(devtools(persist((set) => ({bears: 0,increase: () => set((state) => ({ bears: state.bears + 1 }))}),{ name: 'bear-storage' }))
)

2.3 状态切片(Slices)

组织大型应用状态:

interface AuthSlice {user: User | nulllogin: (credentials: Credentials) => Promise<void>logout: () => void
}interface TodoSlice {todos: Todo[]addTodo: (todo: Todo) => void
}const createAuthSlice = (set) => ({user: null,login: async (credentials) => {const user = await loginApi(credentials)set({ user })},logout: () => set({ user: null })
})const createTodoSlice = (set) => ({todos: [],addTodo: (todo) => set((state) => ({ todos: [...state.todos, todo] }))
})const useStore = create((set) => ({...createAuthSlice(set),...createTodoSlice(set)
}))

3. 性能优化

3.1 选择性订阅

Zustand 支持细粒度的状态订阅:

function TodoCount() {// 只在 todos.length 变化时重渲染const todoCount = useStore((state) => state.todos.length)return <div>Todo Count: {todoCount}</div>
}

3.2 浅比较

使用 shallow 进行浅比较:

import shallow from 'zustand/shallow'function TodoList() {const { todos, addTodo } = useStore((state) => ({ todos: state.todos, addTodo: state.addTodo }),shallow)return (// 组件实现)
}

4. 实际应用场景

4.1 表单状态管理

interface FormStore {formData: {name: stringemail: string}setField: (field: string, value: string) => voidresetForm: () => void
}const useFormStore = create<FormStore>((set) => ({formData: {name: '',email: ''},setField: (field, value) => set((state) => ({formData: {...state.formData,[field]: value}})),resetForm: () => set({formData: {name: '',email: ''}})
}))

4.2 认证状态管理

interface AuthStore {token: string | nulluser: User | nulllogin: (credentials: Credentials) => Promise<void>logout: () => voidupdateUser: (user: Partial<User>) => void
}const useAuthStore = create<AuthStore>()(persist((set) => ({token: null,user: null,login: async (credentials) => {const { token, user } = await loginApi(credentials)set({ token, user })},logout: () => set({ token: null, user: null }),updateUser: (userData) =>set((state) => ({user: state.user ? { ...state.user, ...userData } : null}))}),{name: 'auth-storage',getStorage: () => localStorage})
)

5. 最佳实践

5.1 Store 组织

// stores/index.ts
import { useAuthStore } from './authStore'
import { useTodoStore } from './todoStore'
import { useUIStore } from './uiStore'export {useAuthStore,useTodoStore,useUIStore
}

5.2 TypeScript 集成

// types.ts
interface Todo {id: stringtitle: stringcompleted: boolean
}interface TodoState {todos: Todo[]loading: booleanerror: string | nulladdTodo: (title: string) => voidtoggleTodo: (id: string) => voidremoveTodo: (id: string) => void
}// todoStore.ts
const useTodoStore = create<TodoState>((set) => ({todos: [],loading: false,error: null,addTodo: (title) => set((state) => ({todos: [...state.todos,{id: Date.now().toString(),title,completed: false}]})),toggleTodo: (id) =>set((state) => ({todos: state.todos.map((todo) =>todo.id === id? { ...todo, completed: !todo.completed }: todo)})),removeTodo: (id) =>set((state) => ({todos: state.todos.filter((todo) => todo.id !== id)}))
}))

总结

在这里插入图片描述

Zustand 的优势在于:

  • 简单直观的 API 设计
  • 无需 Provider 的使用方式
  • 出色的 TypeScript 支持
  • 强大的中间件系统
  • 优秀的性能表现

使用 Zustand 可以帮助我们:

  1. 降低状态管理的复杂度
  2. 提高应用的可维护性
  3. 优化应用性能
  4. 提供更好的开发体验

在选择状态管理方案时,如果你需要一个轻量级但功能强大的解决方案,Zustand 是一个值得考虑的选择。它特别适合中小型应用,但通过良好的状态组织,同样可以胜任大型应用的状态管理需求。

End

相关文章:

【React】状态管理之Zustand

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 状态管理之Zustand引言1. Zustand 的核心特点1.1 简单直观的 API1.2 无需 Provi…...

Vue3打包自动生成版本JSON文件,添加系统版本检查,实现系统自动更新提示

实现该功能一共有三步。废话不多说&#xff0c;直接上代码&#xff01;&#xff01;&#xff01; 第一步&#xff1a;打包时自动生成版本信息的js文件&#xff0c;versionUpdate.js import fs from fs; import path from path; import { ElMessageBox } from element-plus; i…...

海量数据有限内存系列问题解决方案

1. 排序问题 有限数据充足内存&#xff1a;内存中有十万整数&#xff0c;对所有数据进行排序。 内部排序即可 单节点海量数据有限内存&#xff1a;某台机器有一个文件&#xff0c;文件中包含六十亿整数&#xff0c;一个整数一行&#xff0c;可用内存1G&#xff0c;对所有数据…...

FFmpeg 4.3 音视频-多路H265监控录放C++开发十四,总结编码过程,从摄像头获得数据后,转成AVFrame,然后再次转成AVPacket,

也就是将摄像头采集到的YUV 的数据换成 AVFrame&#xff0c;然后再次转成 AVPacket&#xff0c;那么这AVPakcet数据要怎么办呢&#xff1f;分为三种情况&#xff1a; 一种是将AVPacket存储成h264文件&#xff0c;由于h264编码器在将avframe变成avpacket的时候就是按照h264的格…...

内容占位符:Kinetic Loader HTML+CSS 使用CSS制作三角形原理

内容占位符 前言 随着我们对HTML和CSS3的学习逐渐深入&#xff0c;相信大家都已经掌握了网页制作的基础知识&#xff0c;包括如何使用HTML标记构建网页结构&#xff0c;以及如何运用CSS样式美化页面。为了进一步巩固和熟练这些技能&#xff0c;今天我们一起来完成一个有趣且实…...

麒麟nginx配置

一、配置负载均衡 配置麒麟的yum源 vim /etc/yum.repos.d/kylin_aarch64.repo Copy 删除原来内容&#xff0c;写入如下yum源 [ks10-adv-os] name Kylin Linux Advanced Server 10 - Os baseurl http://update.cs2c.com.cn:8080/NS/V10/V10SP2/os/adv/lic/base/aarch64/ …...

如何在 Ubuntu 上安装 Emby 媒体服务器

Emby 是一个开源的媒体服务器解决方案&#xff0c;它能让你整理、流媒体播放和分享你的个人媒体收藏&#xff0c;包括电影、音乐、电视节目和照片。Emby 帮你集中多媒体内容&#xff0c;让你无论在家还是在外都能轻松访问。它还支持转码&#xff0c;让你能够播放各种格式的内容…...

Mac上详细配置java开发环境和软件(更新中)

文章目录 概要JDK的配置JDK下载安装配置JDK环境变量文件 Idea的安装Mysql安装和配置Navicat Premium16.1安装安装Vscode安装和配置Maven配置本地仓库配置阿里云私服Idea集成Maven 概要 这里使用的是M3型片 14.6版本的Mac 用到的资源放在网盘 链接: https://pan.baidu.com/s/17…...

jmeter常用配置元件介绍总结之定时器

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之定时器 5.定时器5.1.固定定时器5.2.统一随机定时器5.3.Precise Throughput Timer5.4.Constant Throughput Timer5.5.Synchronizing Timer5.6.泊松随机定时器5.7.高斯随机定时器 5.定时器 5.1.固定定时器 固定定时器Cons…...

Spring——提前编译

提前编译&#xff1a;AOT AOT概述 JIT与AOT的区别 JIT和AOT 这个名词是指两种不同的编译方式&#xff0c;这两种编译方式的主要区别在于是否在“运行时”进行编译 &#xff08;1&#xff09;JIT&#xff0c; Just-in-time,动态(即时)编译&#xff0c;边运行边编译&#xff1…...

乐理的学习(音程)

二度&#xff0c;三度&#xff0c;六度&#xff0c;七度的大n度都是直接的音名到音名&#xff0c;如#A到#G的&#xff0c;这样为大n度 而这个基础上向内收&#xff0c;收半音为小n度&#xff0c;在小n度再收&#xff0c;为减n度 在大n度的基础上再向外扩半音&#xff0c;为增…...

【网络】数据链路层协议——以太网,ARP协议

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解什么是以太网协议和ARP协议。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xf…...

Linux分区、挂载、配额、逻辑卷、RAID、系统综合状态查看

分区与挂载 fdisk fdisk 命令是一个用于磁盘分区管理的命令行工具&#xff0c;可以用来创建、删除、调整分区等操作。常用的 fdisk 命令选项包括&#xff1a; fdisk -l&#xff1a;列出系统中的所有磁盘分区信息。 fdisk /dev/sdX&#xff1a;打开指定磁盘进行分区操作。 n&…...

3D Gaussian Splatting 代码层理解之Part1

2023 年初,来自蔚蓝海岸大学和 马克斯普朗克学会的作者发表了一篇题为“用于实时现场渲染的 3D 高斯泼溅”的论文。该论文提出了实时神经渲染的重大进步,超越了NeRF等以前方法的实用性。高斯泼溅不仅减少了延迟,而且达到或超过了 NeRF 的渲染质量,在神经渲染领域掀起了一场…...

Qt小知识-Q_GLOBAL_STATIC

你还在为创建全局静态对象烦恼嘛&#xff0c;它来了&#xff01;它来了&#xff01; qt5提供了两个宏定义Q_GLOBAL_STATIC和Q_GLOBAL_STATIC_WITH_ARGS来实现。可以创建一个全局静态对象&#xff0c;对象在第一次使用时初始化自身&#xff0c;这意味着它不会增加应用程序或库的…...

【SpringBoot】使用过滤器进行XSS防御

在Spring Boot中&#xff0c;我们可以使用注解的方式来进行XSS防御。注解是一种轻量级的防御手段&#xff0c;它可以在方法或字段级别对输入进行校验&#xff0c;从而防止XSS攻击。 而想对全局的请求都进行XSS防御可以使用servlet中的过滤器或者spring mvc中的拦截器&#xff…...

创建vue插件,发布npm

开发步骤&#xff1a;1.创建一个vue项目&#xff0c;2.开发一个组件。 3.注册成插件。 4.vite和package.json配置。5.发布到npm &#xff11;.创建一个vue项目 npm create vuelatest 生成了vue项目之后&#xff0c;得到了以下结构。 在src下创建个plugins目录。用于存放开发的…...

【Android Compose原创组件】可拖动滚动条的完美实现

项目背景 我在使用安卓Compose开发自己的【JK管理器】的过程中&#xff0c;很多地方都需要使用滚动条&#xff0c;在Github上也有实现的比较好&#xff0c;但是大多都是基于View&#xff08;我要的是Compose啊&#xff09;。 在研究Android 官方示例项目 nowinandroid 中&…...

【模块一】kubernetes容器编排进阶实战之资源管理核心概念

kubernetes 资源管理核心概念 k8s的设计理念—分层架构 CRI-container runtime interface-容器运行接口 CNI-container network interface-容器网络接口 CSI-container storage interface-容器存储接口 k8s的设计理念—API设计原则 https://www.kubernetes.org.cn/kubernete…...

用Python设置PowerPoint幻灯片背景

使用Python自动化处理Office文档&#xff0c;如PowerPoint演示文稿&#xff0c;是提高效率和创造力的重要手段。设置PowerPoint幻灯片背景不仅能够增强演示文稿的视觉吸引力&#xff0c;还能帮助传达特定的情感或信息&#xff0c;使观众更加投入。通过编程方式批量修改幻灯片背…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...