react的状态管理

状态(State)是 React 中用于存储组件数据的特殊对象,它可以影响组件的渲染输出。状态管理的核心目标是确保数据的一致性、可预测性以及组件之间的数据流。

每个 React 组件都可以拥有自己的状态。在类组件中,状态通过 this.state 来管理,而在函数组件中,可以使用 useState Hook 来添加本地状态。

props(属性)是组件之间的数据传递机制。父组件可以通过 props 将其状态向下传递给子组件。但是,props 是单向数据流,子组件不能直接修改通过 props 接收的数据。当多个组件需要共享相同的状态时,可以将状态提升到它们最近的共同父组件中。这样,所有需要这个状态的组件都可以通过 props 访问它。

Context API 允许你无需明确通过组件树逐层传递 props,就能在组件树中共享数据。它适用于那些需要在应用程序的多个层级中访问的数据,如用户认证状态、主题设置等。

对于更复杂的应用程序,可能需要更强大的状态管理解决方案。这就是外部状态管理库发挥作用的地方,如 Redux、MobX、Zustand 等。这些库提供了更丰富的功能,如时间旅行调试、持久化、中间件支持等。

状态管理需要解决哪些关键问题?

  1. 数据一致性与可预测性:确保应用中的数据在任何时候都是一致的,并且状态变化是可预测的。

  2. 组件间通信:提供组件之间,特别是非直接父子关系的组件间共享和传递状态的机制。

  3. 可维护性与可扩展性:随着应用规模的增长,状态管理应保持代码的可维护性,并能够适应更复杂的数据流。

  4. 性能优化:减少不必要的组件重渲染,确保状态更新能够高效地触发所需的组件更新。

  5. 调试与错误处理:提供调试工具和错误处理机制,帮助开发者理解和维护状态变化,同时处理状态更新中的错误。

  6. 持久化与安全性:支持数据的持久化存储,并确保状态管理过程中的安全性,防止未授权访问。

外部状态管理库

随着 React 生态系统的不断发展,新的状态管理库不断涌现,以满足新的开发需求和解决现有库的不足。不同的项目根据其规模和复杂度需要不同级别的状态管理。小型项目可能只需要简单的状态管理,而大型项目则需要更复杂、更健壮的解决方案。

在React项目中,常用的外部状态管理库有:

  1. Redux:这是一个集中式的状态管理库,它通过单个store来存储整个应用的状态。Redux强调状态的不可变性和数据流的单向性,适用于大型应用和需要高度可预测状态变化的场景。

  2. MobX:MobX是一个简单且可扩展的状态管理库,采用观察者模式来实现状态管理。它提供了更简单直观的API,支持装饰器语法,易于学习且灵活,适合中小型项目。

  3. Zustand:Zustand是一个轻量级的状态管理库,它提供了简单的方式来管理React应用程序中的状态。它的主要特点是易于使用和轻量级,可以用于中心化或非中心化的数据流。

  4. Recoil:Recoil是Facebook开发的一个状态管理库,专为React设计,以解决复杂状态管理的痛点。它使用原子和选择器来管理状态,支持并行和异步操作。

  5. Jotai:Jotai是一个基于原子化的轻量级状态管理库,它借鉴了Redux和Recoil的设计。Jotai简单易用、无需过度配置、支持即时更新,适合小型到中型项目。

我们可以通过npmtrends查看这些库的下载量对比

npmtrends各状态管理库下载量对比

总体来看,Redux 仍然是最流行的状态管理库,尽管它的安装包大小较大。Zustand 作为一个较新的库,正在获得越来越多的关注,其轻量级的特点可能是吸引开发者的一个因素。MobX 和 Jotai 也有稳定的用户基础,但它们的下载量和社区活跃度低于 Redux 和 Zustand。

Zustand

Zustand 是一个轻量级且易于使用的状态管理库,特别适用于 React 应用程序。它的优势包括:

  1. 轻量级:Zustand 的整个代码库非常小巧,gzip 压缩后仅有 1KB,对项目性能影响极小。
  2. 简洁的 API:提供了简洁明了的 API,能够快速上手并使用它来管理项目状态。
  3. 基于钩子:Zustand 使用 React 的钩子机制作为状态管理的基础,与函数式组件和钩子的编程模型紧密配合,使得状态管理变得非常自然和无缝。
  4. 易于集成:可以轻松地与其他 React 库(如 Redux、MobX 等)共存,方便逐步迁移项目状态管理。
  5. 支持 TypeScript:Zustand 支持 TypeScript,让项目更具健壮性。
  6. 灵活性:允许根据项目需求自由组织状态树,适应不同的项目结构。
  7. 可拓展性:提供了中间件 (middleware) 的概念,允许你通过插件的方式扩展其功能,如日志记录、持久化存储、异步操作等。

然而,Zustand 也存在一些局限性:

  1. 社区规模:与 Redux 或 MobX 等更成熟的库相比,Zustand 的社区规模较小,这可能意味着在寻求帮助或查找资源时会遇到一些挑战。
  2. 学习资源:虽然 Zustand 的文档和示例相对齐全,但可能不如其他流行库那样丰富。
  3. 特定功能支持: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 状态和两个用于改变该状态的动作 incrementdecrement

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 路径中导入的一个工具函数,它对返回的对象进行浅层比较,如果对象的顶层属性和之前的状态一样,即使引用不同,也不会重新渲染组件。

  1. 选择性订阅:只订阅组件需要的状态片段,减少不必要的渲染。
  2. 浅比较:使用 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状态管理的更多相关文章

  1. 借鉴redux,实现一个react状态管理方案

    react状态管理方案有很多,其中最简单的最常用的是redux. redux实现 redux做状态管理,是利用reducer和action实现的state的更新. 如果想要用redux,需要几个步骤 ...

  2. React状态管理相关

    关于React状态管理的一些想法 我最开始使用React的时候,那个时候版本还比较低(16版本以前),所以状态管理都是靠React自身API去进行管理,但当时最大的问题就是跨组件通信以及状态同步和状态 ...

  3. Sentry 开发者贡献指南 - 前端 React Hooks 与虫洞状态管理模式

    系列 Sentry 开发者贡献指南 - 前端(ReactJS生态) Sentry 开发者贡献指南 - 后端服务(Python/Go/Rust/NodeJS) 什么是虫洞状态管理模式? 您可以逃脱的最小 ...

  4. 纯粹极简的react状态管理组件unstated

    简介 unstated是一个极简的状态管理组件 看它的简介:State so simple, it goes without saying 对比 对比redux: 更加灵活(相对的缺点是缺少规则,需要 ...

  5. react状态管理器之mobx

    react有几种状态管理器,今天先来整理一下mobx状态管理器,首先了解一下什么是mobx 1.mobx成员: observable action 可以干嘛: MobX 的理念是通过观察者模式对数据做 ...

  6. 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 + ...

  7. React状态管理之redux

    其实和vue对应的vuex都是差不多的东西,这里稍微提一下(安装Redux略过): import { createStore, combineReducers, applyMiddleware } f ...

  8. 你再也不用使用 Redux、Mobx、Flux 等状态管理了

    Unstated Next readme 的中文翻译 前言 这个库的作者希望使用 React 内置 API ,直接实现状态管理的功能.看完这个库的说明后,没有想到代码可以这个玩.短短几行代码,仅仅使用 ...

  9. 使用 react 的 hooks 进行全局的状态管理

    使用 react 的 hooks 进行全局的状态管理 React 最新正式版已经支持了 Hooks API,先快速过一下新的 API 和大概的用法. // useState,简单粗暴,setState ...

  10. React 新 Context API 在前端状态管理的实践

    本文转载至:今日头条技术博客 众所周知,React的单向数据流模式导致状态只能一级一级的由父组件传递到子组件,在大中型应用中较为繁琐不好管理,通常我们需要使用Redux来帮助我们进行管理,然而随着Re ...

随机推荐

  1. 用C#写个PDF批量合并工具简化日常工作

    一. 前言 由于项目需要编写大量的材料,以及各种签字表格.文书等,最后以PDF作为材料交付的文档格式,过程文档时有变化或补充,故此处理PDF文档已经成为日常工作的一部分. 网上有各种PDF处理工具,总 ...

  2. [OI] 指针与迭代器

    取地址与解引用 一般来说,我们有一个取地址符 & 可以返回该变量的地址. int main(){ int a; cout<<&a; } 0x6ffe1c 如果我们现在有一个 ...

  3. 【赵渝强老师】MySQL高可用架构:MHA

    MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了 automating master failover 功能.MHA 在监控到 master 节 ...

  4. PasteForm最佳CRUD实践,实际案例PasteTemplate详解之3000问(二)

    作为"贴代码"力推的一个CRUD实践项目PasteTemplate,在对现有的3个项目进行实战后效果非常舒服!下面就针对PasteForm为啥我愿称为最佳CRUD做一些回答: 哪里 ...

  5. LeetCode 1349. 参加考试的最大学生数 (状压DP 或 二分图最大独立子集)

    给你一个 m * n 的矩阵 seats 表示教室中的座位分布.如果座位是坏的(不可用),就用 '#' 表示:否则,用 '.' 表示. 学生可以看到左侧.右侧.左上.右上这四个方向上紧邻他的学生的答卷 ...

  6. dotnet Core 静态方法和构造方法

    // 静态方法: // 特点:1.生命周期一旦创建-应用结束 才会结束 2.全局的 3.效率高(放在内存中) // 用户:用户登录,系统配置信息,系统设置,SQLHelper // 注意:静态的东西创 ...

  7. 浅析Jvm

    浅析Jvm 基本概念 引言 Java 虚拟机(JVM,Java Virtual Machine)是 Java 生态系统的核心组成部分,它为 Java 应用程序提供了一个运行环境.JVM 的主要职责是将 ...

  8. 云原生周刊:Meshery v0.70 发布 | 2024.1.22

    开源项目推荐 flux-cluster-template 该项目用于部署由 Flux.SOPS.GitHub Actions.Renovate.Cilium 等支持的 Kubernetes 集群,专注 ...

  9. 6.19 成都站云原生 Meetup,KubeSphere 和 APISIX 等你来!

    以容器技术和容器编排为基础的云原生应用,被越来越多的企业用户接受和使用,并且在生产环境中使用容器技术的比例逐年增加.KubeSphere 作为一款面向应用的开源容器混合云,经过 3 年的发展和 10 ...

  10. PHP将整形数字转为Excel下标

    1.背景 这两天在接到一个需求,需要导出一个班级所有学员的所有成绩,在最后excel表处理的时候发现导出的列超过了26列,后面会出现AA之类的下标,所以写了一个函数把数字整型转为Excel对应的下标. ...