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. 所见即所得,赋能RAG:PDF解析里的段落识别

    前几天,有一位用户使用OCR产品识别多栏论文后向我们询问:要怎么解决不合适的断句.分段以及错误阅读顺序的问题? 我们用一个相似案例为大家直观展示这位用户遇到的情况. 如图中的多栏期刊,如果用OCR识别 ...

  2. Angular 18+ 高级教程 – Angular 的局限 の Query Elements

    前言 熟悉 Angular 的朋友都知道,Angular 有非常多的局限,许多事情它都做不好,打开 Github 一堆 2016 - 2017 的 Issues,时至今日都没有解决. 原因也很简单 - ...

  3. CSS – Reset CSS / Base CSS

    前言 许多 element tag 都有自带的 style. 比如 h1 默认 font-size 是 2 em anchor 默认颜色是 blue 大部分默认 style 并不会是开发人员期望的效果 ...

  4. 课时04:了解HTTP网络协议

    什么是HTTP协议 HTTP(HyperText Transfer Protocol)叫超文本传输协议,它是web服务器和客户端直接进行数据传输的规则,是一个无状态的应用层协议. HTTP协议工作原理 ...

  5. 【赵渝强老师】MongoDB中的索引(上)

    索引是提高查询查询效率最有效的手段.索引是一种特殊的数据结构,索引以易于遍历的形式存储了数据的部分内容(如:一个特定的字段或一组字段值),索引会按一定规则对存储值进行排序,而且索引的存储位置在内存中, ...

  6. 《Vue.js 设计与实现》读书笔记 - 第8章、挂载与更新

    第8章.挂载与更新 8.1 挂载子节点和元素的属性 扩展子元素的类型可以为数组,并判断如果是数组的话,就先依次挂载所有的子元素. 同时新增节点属性.属性可以通过 el.setAttribute 添加到 ...

  7. dwc3 usb debugfs(otg switch)

    1. driver driver/usb/dwc3/debugfs.c dwc3 probe ->dwc3 debugfs init() 2. enable debugfs mount -t d ...

  8. 03-jsx中使用js表达式

    // 在jsx中使用 js 表达式 /// 通过一个 {} 展示变量即可 vue 中使用 {{}} 展示js表达式 // 什么是js表达式 有结果的 import reactDom from &quo ...

  9. RocketMQ 5.0 如何配置TLS加密传输?

    本文作者:李伟,社区里大家叫小伟,Apache RocketMQ Committer,RocketMQ Python客户端项目Owner ,Apache Doris Contributor,腾讯云Ro ...

  10. Maven 项目获取 git 分支、提交等信息

    git-commit-id-plugin 是一个 Maven 插件,用于在 Maven 项目的构建过程中自动获取 git 仓库的信息,如最后一次提交的 ID.分支名称.构建时间等,并将这些信息注入到项 ...