又一知名前端库停止维护...

开发 前端
在 2025 年的当下,提到 React 状态管理,我依旧首推 Zustand,它比 Redux、Mobx 的思维模型更简单,没有那么复杂的样板代码要写。下面就来简单看看 Zustand 的用法。

最近,GitHub 上拥有 20k Star 的 React 状态管理库 Recoil 正式停止维护,其 GitHub 仓库已被归档。Recoil 由 Meta 公司开源,然而,值得注意的是,Meta 已解雇 Recoil 团队的所有成员,且该库已有接近两年的时间未进行更新,因此其停止维护似乎已成定局。

图片图片

在 2025 年的当下,提到 React 状态管理,我依旧首推 Zustand,它比 Redux、Mobx 的思维模型更简单,没有那么复杂的样板代码要写。下面就来简单看看 Zustand 的用法。

Zustand 是什么?

Zustand 是一个小型、快速且可扩展的状态管理解决方案,基于简化的 Flux 原则,使用基于 Hooks 的 API,不包含样板代码且不具有强制性。Zustand 在 Github 拥有近 50k Star,其 npm 每周下载量近 500w。

Zustand 的特点如下:

  • 简单性:与 Redux 相比,Zustand 更简单且不具有强制性,不需要像 React-Redux 那样使用 Context Provider 包裹应用。
  • 基于 Hooks:提供了直观易用的 Hooks 接口,让开发者可以轻松地与状态进行交互,减少样板代码。
  • 单一数据源:整个应用的状态被集中存储在一个 store 中,该 store 可以被分割成多个状态切片,每个切片负责一部分应用逻辑。
  • 不可变性:状态更新是不可变的,更新状态时需要创建一个新的状态对象,而不是直接修改现有状态,从而简化状态管理并防止常见的可变性相关错误。
  • 订阅和选择性响应性:组件可以订阅特定的状态切片,并在这些切片发生变化时自动重新渲染。
  • 细粒度依赖跟踪:使用代理实现对状态变化的细粒度跟踪,确保只有当相关状态发生变更时才会触发组件的重新渲染,最大限度减少了不必要的更新。

Zustand 的使用

基本使用

安装 Zustand:首先,使用 npm 来安装 Zustand:

npm install zustand

创建 Store:在 Zustand 中,Store是通过create函数创建的。每个Store都包含状态和处理状态的函数。

import { create } from 'zustand';

const useStore = create((set) => ({
  count: 0, // 初始状态
  increment: () => set((state) => ({ count: state.count + 1 })), // 增加count的函数
  decrement: () => set((state) => ({ count: state.count - 1 })), // 减少count的函数
}));

create函数接受一个回调函数,该回调函数接受一个set函数作为参数,用于更新状态。在这个回调函数中,定义了一个count状态和两个更新函数increment和decrement。

使用 Store:在组件中,可以使用自定义的 Hooks(上面的useStore)来获取状态和更新函数,并在组件中使用它们。

import React from 'react';
import { useStore } from './store';

function Counter() {
  const { count, increment, decrement } = useStore();
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

下面是一个较复杂的状态管理:

import create from 'zustand';

const useUserStore = create((set) => ({
  user: {
    name: '',
    age: 0,
    email: ''
  },
  setUserName: (newName) => set((state) => ({ user: {...state.user, name: newName } })),
  setUserAge: (newAge) => set((state) => ({ user: {...state.user, age: newAge } })),
  setUserEmail: (newEmail) => set((state) => ({ user: {...state.user, email: newEmail } }))
}));

订阅特定状态片段

在 Zustand 中,如果有一个包含多个状态的store,但在组件中只需要订阅其中一个状态,可以通过解构赋值从useStore返回的完整状态对象中提取需要的状态。Zustand的智能选择器功能允许这样做,而不会导致不必要的重新渲染。下面来看个简单的例子。

在这个store中,有两个状态:count和name,以及两个更新这些状态的函数。

// store.js
import { create } from 'zustand';
 
const useStore = create((set) => ({
  count: 0,
  name: 'Zustand Store',
  increment: () => set((state) => ({ count: state.count + 1 })),
  setName: (newName) => set({ name: newName }),
}));
 
export default useStore;

现在,在组件中,如果只想订阅count状态,可以这样做:

// MyComponent.js
import React from 'react';
import useStore from './store';

function MyComponent() {
  // 使用解构赋值从store状态中提取count
  const { count } = useStore((state) => ({ count: state.count }));

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
}

export default MyComponent;

在组件中,传递了一个选择器函数给useStore。这个选择器函数接受当前的store状态作为参数,并返回需要的部分状态(在这个例子中是count)。这样,Zustand就知道只需要在count状态变化时通知这个组件。

如果想要订阅多个状态,但不想订阅全部状态,可以在选择器函数中返回多个状态:

const { count, name } = useStore((state) => ({ count: state.count, name: state.name }));

使用中间件

Zustand 支持中间件,可以通过中间件来扩展其功能。例如,可以使用内置的persist中间件将状态保存到本地存储,或者使用devtools中间件在浏览器的 Redux DevTools 扩展中查看和调试 Zustand store 的状态变化等。

在下面的例子中,使用persist中间件将count状态保存到浏览器的 localStorage 中:

import { create } from 'zustand';
import { persist } from 'zustand/middleware';

const useCounterStore = create(
  persist(
    (set) => ({
      count: 0,
      increment: () => set((state) => ({ count: state.count + 1 })),
      decrement: () => set((state) => ({ count: state.count - 1 })),
    }),
    {
      name: 'counter-storage', // 本地存储的key
    }
  )
);

我们还可以根据需求来自定义中间件,格式如下:

const myCustomMiddleware = (config) => (set, get, api) => {
  // 预处理逻辑
  
  const result = config(set, get, api); // 调用原始配置
  
  // 后处理逻辑
  
  return result;
};

然后,可以像这样来应用自定义中间件:

import { create } from 'zustand';

const createStore = (set) => ({
  count: 0,
  increase: () => set((state) => ({ count: state.count + 1 })),
});

const useStore = create(myCustomMiddleware(createStore));

export default useStore;

如果想同时应用多个中间件,可以直接将它们链式调用:

import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';

const useStore = create(
  devtools(persist(createStore, { name: 'counter-storage' }), { name: 'my-counter-store' })
);

export default useStore;

异步支持

Zustand 默认支持异步操作,最直接的方式是在创建 store 的时候定义异步函数。可以像定义同步动作一样定义异步动作,只需确保它们返回 Promise。

import { create } from 'zustand';

const useStore = create((set) => ({
  data: null,
  loading: false,
  error: null,
  
  fetchData: async () => {
    set({ loading: true, error: null }); // 设置加载状态
  
    try {
      const response = await fetch('https://api.example.com/data');
      if (!response.ok) throw new Error('Network response was not ok');
      const data = await response.json();
      set({ data, loading: false }); // 更新状态为成功
    } catch (err) {
      set({ error: err.message, loading: false }); // 更新状态为失败
    }
  },
}));

export default useStore;
责任编辑:姜华 来源: 前端充电宝
相关推荐

2024-10-30 09:15:09

React前端库工具库

2023-09-11 00:11:55

2023-09-08 10:21:21

2021-04-13 15:09:16

CentOS6EOL项目

2021-10-20 22:47:17

Windows 10Windows微软

2020-04-28 16:12:50

前端JavaScript代码

2010-12-22 09:31:13

PHP 5.2

2018-12-11 15:00:37

2021-01-27 09:52:39

CentOSRed HatLinux

2020-02-26 08:00:20

恶意删库拘留

2024-02-01 00:13:28

React前端开发

2011-03-24 16:38:00

Exchange数据库维护

2010-02-25 15:06:27

51CTO

2022-06-20 09:45:48

Python开源可视化库

2011-08-01 13:59:22

Oracle数据库命名空间

2012-08-23 11:03:55

IE浏览器

2024-10-30 12:26:44

2022-06-10 07:45:09

CentOS国产操作系统

2021-11-10 09:57:11

业务华为技术
点赞
收藏

51CTO技术栈公众号