zustand:基于hooks的react状态管理
react的状态管理
状态(State)是 React 中用于存储组件数据的特殊对象,它可以影响组件的渲染输出。状态管理的核心目标是确保数据的一致性、可预测性以及组件之间的数据流。
每个 React 组件都可以拥有自己的状态。在类组件中,状态通过 this.state
来管理,而在函数组件中,可以使用 useState
Hook 来添加本地状态。
props(属性)是组件之间的数据传递机制。父组件可以通过 props 将其状态向下传递给子组件。但是,props 是单向数据流,子组件不能直接修改通过 props 接收的数据。当多个组件需要共享相同的状态时,可以将状态提升到它们最近的共同父组件中。这样,所有需要这个状态的组件都可以通过 props 访问它。
Context API 允许你无需明确通过组件树逐层传递 props,就能在组件树中共享数据。它适用于那些需要在应用程序的多个层级中访问的数据,如用户认证状态、主题设置等。
对于更复杂的应用程序,可能需要更强大的状态管理解决方案。这就是外部状态管理库发挥作用的地方,如 Redux、MobX、Zustand 等。这些库提供了更丰富的功能,如时间旅行调试、持久化、中间件支持等。
状态管理需要解决哪些关键问题?
数据一致性与可预测性:确保应用中的数据在任何时候都是一致的,并且状态变化是可预测的。
组件间通信:提供组件之间,特别是非直接父子关系的组件间共享和传递状态的机制。
可维护性与可扩展性:随着应用规模的增长,状态管理应保持代码的可维护性,并能够适应更复杂的数据流。
性能优化:减少不必要的组件重渲染,确保状态更新能够高效地触发所需的组件更新。
调试与错误处理:提供调试工具和错误处理机制,帮助开发者理解和维护状态变化,同时处理状态更新中的错误。
持久化与安全性:支持数据的持久化存储,并确保状态管理过程中的安全性,防止未授权访问。
外部状态管理库
随着 React 生态系统的不断发展,新的状态管理库不断涌现,以满足新的开发需求和解决现有库的不足。不同的项目根据其规模和复杂度需要不同级别的状态管理。小型项目可能只需要简单的状态管理,而大型项目则需要更复杂、更健壮的解决方案。
在React项目中,常用的外部状态管理库有:
Redux:这是一个集中式的状态管理库,它通过单个store来存储整个应用的状态。Redux强调状态的不可变性和数据流的单向性,适用于大型应用和需要高度可预测状态变化的场景。
MobX:MobX是一个简单且可扩展的状态管理库,采用观察者模式来实现状态管理。它提供了更简单直观的API,支持装饰器语法,易于学习且灵活,适合中小型项目。
Zustand:Zustand是一个轻量级的状态管理库,它提供了简单的方式来管理React应用程序中的状态。它的主要特点是易于使用和轻量级,可以用于中心化或非中心化的数据流。
Recoil:Recoil是Facebook开发的一个状态管理库,专为React设计,以解决复杂状态管理的痛点。它使用原子和选择器来管理状态,支持并行和异步操作。
Jotai:Jotai是一个基于原子化的轻量级状态管理库,它借鉴了Redux和Recoil的设计。Jotai简单易用、无需过度配置、支持即时更新,适合小型到中型项目。
我们可以通过npmtrends查看这些库的下载量对比
总体来看,Redux 仍然是最流行的状态管理库,尽管它的安装包大小较大。Zustand 作为一个较新的库,正在获得越来越多的关注,其轻量级的特点可能是吸引开发者的一个因素。MobX 和 Jotai 也有稳定的用户基础,但它们的下载量和社区活跃度低于 Redux 和 Zustand。
Zustand
Zustand 是一个轻量级且易于使用的状态管理库,特别适用于 React 应用程序。它的优势包括:
- 轻量级:Zustand 的整个代码库非常小巧,gzip 压缩后仅有 1KB,对项目性能影响极小。
- 简洁的 API:提供了简洁明了的 API,能够快速上手并使用它来管理项目状态。
- 基于钩子:Zustand 使用 React 的钩子机制作为状态管理的基础,与函数式组件和钩子的编程模型紧密配合,使得状态管理变得非常自然和无缝。
- 易于集成:可以轻松地与其他 React 库(如 Redux、MobX 等)共存,方便逐步迁移项目状态管理。
- 支持 TypeScript:Zustand 支持 TypeScript,让项目更具健壮性。
- 灵活性:允许根据项目需求自由组织状态树,适应不同的项目结构。
- 可拓展性:提供了中间件 (middleware) 的概念,允许你通过插件的方式扩展其功能,如日志记录、持久化存储、异步操作等。
然而,Zustand 也存在一些局限性:
- 社区规模:与 Redux 或 MobX 等更成熟的库相比,Zustand 的社区规模较小,这可能意味着在寻求帮助或查找资源时会遇到一些挑战。
- 学习资源:虽然 Zustand 的文档和示例相对齐全,但可能不如其他流行库那样丰富。
- 特定功能支持:Zustand 可能在某些特定功能或高级用例的支持上不如其他状态管理库全面。
总的来说,Zustand 提供了一种简单、直观且高效的状态管理方式,尤其适合那些希望避免 Redux 等库复杂性,同时需要一个易于上手和轻量级解决方案的开发者。
Zustand使用
安装
首先,你需要通过 npm 或 yarn 将 Zustand 添加到你的项目中:
npm install zustand
yarn add zustand
基础用法
1. 创建一个 Store
创建一个 store 来存储和管理状态。
import create from 'zustand';
const useStore = create(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
decrement: () => set(state => ({ count: state.count - 1 })),
}));
export default useStore;
在这个示例中,我们创建了一个具有 count
状态和两个用于改变该状态的动作 increment
和 decrement
。
2. 在组件中使用 Store
在 React 组件中,你可以使用自定义 Hook useStore
来访问和修改状态。
import React from 'react';
import { useStore } from './store'; // 假设你的 store 文件名为 store.js
function Counter() {
const count = useStore((state) => state.count);
const increment = useStore((state) => state.increment);
const decrement = useStore((state) => state.decrement);
const decrement = useStore((state) => state.decrement);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={decrement}>-</button>
<button onClick={increment}>+</button>
</div>
);
}
export default Counter;
3. 异步操作
import create from 'zustand';
import { getCount } from '@/services'; // 模拟异步请求的接口
const useStore = create((set, get) => ({
count: 0,
params: {id: 1}, // 模拟请求的参数
increment: () => set(state => ({ count: state.count + 1 })),
decrement: () => set(state => ({ count: state.count - 1 })),
getCount: async () => {
const res = await getCount(get().params); // 通过get获取当前store的状态
set({ count: res.data });
}
}));
export default useStore;
在其他组件中调用异步操作
import React, { useEffect } from 'react';
import { useStore } from './store'; // 假设你的 store 文件名为 store.js
function Counter() {
const count = useStore((state) => state.count);
const increment = useStore((state) => state.increment);
const decrement = useStore((state) => state.decrement);
const decrement = useStore((state) => state.decrement);
const getCount = useStore((state) => state.getCount);
useEffect(()=>{
getCount();
}, [])
return (
<div>
<h1>Count: {count}</h1>
<button onClick={decrement}>-</button>
<button onClick={increment}>+</button>
</div>
);
}
export default Counter;
4. 获取多个状态
前文中我们的状态与方法都是单独一句声明的,为什么不直接获取整个状态库呢?
const state = useStore();
这样做可以获取整个 store,但请记住这样做会导致组件在每次状态变化时都重新渲染!
更优雅的实现方式:
import { useShallow } from 'zustand/react/shallow';
const { count, increment, decrement } = useStore(
useShallow((state) => ({
count: state.count,
increment: state.increment,
decrement: state.decrement,
}))
);
// const { count, increment, decrement } = useStore(); // 待验证
useShallow
是从 Zustand 提供的 /shallow
路径中导入的一个工具函数,它对返回的对象进行浅层比较,如果对象的顶层属性和之前的状态一样,即使引用不同,也不会重新渲染组件。
- 选择性订阅:只订阅组件需要的状态片段,减少不必要的渲染。
- 浅比较:使用
useShallow
进行浅比较,减少不必要的渲染。
5. 状态持久化
使用 middleware
来实现状态的持久化。
import create from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware'
const useStoreWithPersistence = create(
persist(
(set, get) => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
decrement: () => set(state => ({ count: state.count - 1 })),
}),
{
name: 'my_zustand_store', // name of the item in the storage (must be unique)
storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used
},
),
);
zustand:基于hooks的react状态管理的更多相关文章
- 借鉴redux,实现一个react状态管理方案
react状态管理方案有很多,其中最简单的最常用的是redux. redux实现 redux做状态管理,是利用reducer和action实现的state的更新. 如果想要用redux,需要几个步骤 ...
- React状态管理相关
关于React状态管理的一些想法 我最开始使用React的时候,那个时候版本还比较低(16版本以前),所以状态管理都是靠React自身API去进行管理,但当时最大的问题就是跨组件通信以及状态同步和状态 ...
- Sentry 开发者贡献指南 - 前端 React Hooks 与虫洞状态管理模式
系列 Sentry 开发者贡献指南 - 前端(ReactJS生态) Sentry 开发者贡献指南 - 后端服务(Python/Go/Rust/NodeJS) 什么是虫洞状态管理模式? 您可以逃脱的最小 ...
- 纯粹极简的react状态管理组件unstated
简介 unstated是一个极简的状态管理组件 看它的简介:State so simple, it goes without saying 对比 对比redux: 更加灵活(相对的缺点是缺少规则,需要 ...
- react状态管理器之mobx
react有几种状态管理器,今天先来整理一下mobx状态管理器,首先了解一下什么是mobx 1.mobx成员: observable action 可以干嘛: MobX 的理念是通过观察者模式对数据做 ...
- react状态管理器(分模块)之redux和redux + react-redux + reducer和redux + react-redux + reducer分模块 + 异步操作redux-thunk
1.回顾 cnpm i redux react-redux redux-thunk -S store/index.js src/index.js src/views/home/index.jsx + ...
- React状态管理之redux
其实和vue对应的vuex都是差不多的东西,这里稍微提一下(安装Redux略过): import { createStore, combineReducers, applyMiddleware } f ...
- 你再也不用使用 Redux、Mobx、Flux 等状态管理了
Unstated Next readme 的中文翻译 前言 这个库的作者希望使用 React 内置 API ,直接实现状态管理的功能.看完这个库的说明后,没有想到代码可以这个玩.短短几行代码,仅仅使用 ...
- 使用 react 的 hooks 进行全局的状态管理
使用 react 的 hooks 进行全局的状态管理 React 最新正式版已经支持了 Hooks API,先快速过一下新的 API 和大概的用法. // useState,简单粗暴,setState ...
- React 新 Context API 在前端状态管理的实践
本文转载至:今日头条技术博客 众所周知,React的单向数据流模式导致状态只能一级一级的由父组件传递到子组件,在大中型应用中较为繁琐不好管理,通常我们需要使用Redux来帮助我们进行管理,然而随着Re ...
随机推荐
- 所见即所得,赋能RAG:PDF解析里的段落识别
前几天,有一位用户使用OCR产品识别多栏论文后向我们询问:要怎么解决不合适的断句.分段以及错误阅读顺序的问题? 我们用一个相似案例为大家直观展示这位用户遇到的情况. 如图中的多栏期刊,如果用OCR识别 ...
- Angular 18+ 高级教程 – Angular 的局限 の Query Elements
前言 熟悉 Angular 的朋友都知道,Angular 有非常多的局限,许多事情它都做不好,打开 Github 一堆 2016 - 2017 的 Issues,时至今日都没有解决. 原因也很简单 - ...
- CSS – Reset CSS / Base CSS
前言 许多 element tag 都有自带的 style. 比如 h1 默认 font-size 是 2 em anchor 默认颜色是 blue 大部分默认 style 并不会是开发人员期望的效果 ...
- 课时04:了解HTTP网络协议
什么是HTTP协议 HTTP(HyperText Transfer Protocol)叫超文本传输协议,它是web服务器和客户端直接进行数据传输的规则,是一个无状态的应用层协议. HTTP协议工作原理 ...
- 【赵渝强老师】MongoDB中的索引(上)
索引是提高查询查询效率最有效的手段.索引是一种特殊的数据结构,索引以易于遍历的形式存储了数据的部分内容(如:一个特定的字段或一组字段值),索引会按一定规则对存储值进行排序,而且索引的存储位置在内存中, ...
- 《Vue.js 设计与实现》读书笔记 - 第8章、挂载与更新
第8章.挂载与更新 8.1 挂载子节点和元素的属性 扩展子元素的类型可以为数组,并判断如果是数组的话,就先依次挂载所有的子元素. 同时新增节点属性.属性可以通过 el.setAttribute 添加到 ...
- dwc3 usb debugfs(otg switch)
1. driver driver/usb/dwc3/debugfs.c dwc3 probe ->dwc3 debugfs init() 2. enable debugfs mount -t d ...
- 03-jsx中使用js表达式
// 在jsx中使用 js 表达式 /// 通过一个 {} 展示变量即可 vue 中使用 {{}} 展示js表达式 // 什么是js表达式 有结果的 import reactDom from &quo ...
- RocketMQ 5.0 如何配置TLS加密传输?
本文作者:李伟,社区里大家叫小伟,Apache RocketMQ Committer,RocketMQ Python客户端项目Owner ,Apache Doris Contributor,腾讯云Ro ...
- Maven 项目获取 git 分支、提交等信息
git-commit-id-plugin 是一个 Maven 插件,用于在 Maven 项目的构建过程中自动获取 git 仓库的信息,如最后一次提交的 ID.分支名称.构建时间等,并将这些信息注入到项 ...