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. Angular 18+ 高级教程 – HttpClient

    前言 HttpClient 是 Angular 对 XMLHttpRequest 和 Fetch 的封装. HttpClient 的 DX (Developer Experience) 比 XMLHt ...

  2. ASP.NET Core – CORS (Cross-Origin Resource Sharing)

    参考 Docs – Enable Cross-Origin Requests (CORS) in ASP.NET Core 介绍 CORS (Cross-Origin Resource Sharing ...

  3. ASP.NET Core – Program.cs and Startup.cs 小笔记

    前言 ASP.NET Core 6.0 以后, 默认模板去掉了 Program.cs 的 namespace, class 和 Startup.cs, 一开始看会有点懵. 这篇大概记入一下, prog ...

  4. linux那些事之页迁移(page migratiom)

    Page migration 页迁移技术是内核中内存管理的一种比较重要的技术,最早该技术诞生于NUMA系统中(Page migration [LWN.net]),后续由于内存规整以及CMA和COW技术 ...

  5. Java日期时间API系列31-----Jdk8中java.time包中的新的日期时间API类,时间戳的获取方式对比、转换和使用。

    时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到.Java中本来已经有相关获取时间戳的方法,Java8后增加新的类In ...

  6. 数据库运维实操优质文章文档分享(含Oracle、MySQL等) | 2024年8月刊

    本文为大家整理了墨天轮数据社区2024年8月发布的优质技术文章/文档,主题涵盖Oracle.MySQL.PostgreSQL等主流数据库系统以及国产数据库的技术实操,从基础的安装配置到复杂的故障排查, ...

  7. 04-react的基本:条件渲染

    import reactDom from "react-dom" // 条件渲染 if else let loading = false // 写一个函数用于加载 const lo ...

  8. 001 (Python+水论文合集)为什么录这个合集,这个合集会讲哪些内容?

    博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...

  9. 关于使用plsql操作oracle的一点小技巧和几个常用的查询语句

    plsql是什么: 就是这个,专门操作oracle的一个工具,好用还免费. 创建一个测试表: create table Student( Id number not null, Name varcha ...

  10. KubeSphere 后端源码深度解析

    这篇文章我们将学习在 vscode 上的 ssh remote 插件基础上,尝试 debug 和学习 KubeSphere 后端模块架构. 前提 安装好 vscode 以及 ssh remote co ...