放弃Redux吧,转投Zustand吧

Zustand是什么

Zustand 是一个为 React 应用程序设计的开源状态管理库,它旨在提供一种简单、轻量级且易于使用的方式来管理应用程序的状态。它是由 Max Stoiber 创建的,并且得到了社区的广泛支持和使用。

Zustand 的核心思想是将状态管理与组件分离,从而使得状态管理更加集中化,同时保持了 React 的响应性和组件的可重用性。它提供了一种简单的 API,使得开发者能够轻松地在应用程序中的任何地方访问和修改状态。 使用 Zustand,开发者可以通过创建一个 store 来存储和管理应用程序的状态。这个 store 是通过调用 createStore 方法并传入一个包含状态和操作的 object 来创建的。

Zustand 与其他状态管理库 如 Redux 和 MobX 相比有什么优势?

Zustand 是一个为 React 应用程序设计的状态管理库,与其他流行的状态管理库如 Redux 和 MobX 相比,它提供了一些独特的优势和特性。以下是 Zustand 相对于 Redux 和 MobX 的一些主要优势:

1. 简单性和易用性

Zustand 提供了一个非常简单和直观的 API,使得开发者能够轻松地创建和管理状态。与 Redux 相比,Zustand 不需要定义复杂的 reducer、action 类型和 action 创建器。与 MobX 相比,Zustand 避免了使用装饰器和 Proxy,使得代码更加直观和易于理解。

2. 集成和兼容性

Zustand 与 React 的集成非常紧密,它利用了 React 的上下文和钩子系统来提供状态管理功能。这意味着在使用 React 应用程序时,Zustand 可以无缝地与现有的组件和钩子一起工作。此外,Zustand 还支持 React Concurrent 模式,确保在最新的 React 版本中也能正常工作。

3. 性能优化

Zustand 通过自动缓存状态值来减少不必要的组件渲染,从而提高性能。它还解决了 Redux 中的“死节点”问题,即在某些情况下,子组件可能无法正确更新的问题。此外,Zustand 通过使用 React 的上下文和钩子系统,避免了 Context loss 问题,这在某些复杂的组件结构中可能会出现。

4. 中间件支持

Zustand 支持大量的中间件,如 Immer、Redux 中间件等,这使得开发者可以根据需要轻松地扩展 Zustand 的功能。这些中间件可以帮助处理不可变状态的更新、异步操作等复杂场景。

5. 状态共享和访问

Zustand 使得在应用程序的任何地方共享和访问状态变得非常容易。开发者可以使用 useStore 钩子来获取和更新状态,而不需要通过多层的组件传递 props 或者使用 React Context。

6. 调试和开发体验

Zustand 提供了良好的调试体验,它与 Redux DevTools 兼容,使得开发者可以轻松地检查和调试状态变化。此外,Zustand 还提供了一些内置的调试功能,如 useDebugValue 钩子,可以帮助开发者更好地理解状态的变化。

7. 灵活性和可扩展性

Zustand 允许开发者通过自定义钩子和中间件来扩展其功能。这意味着开发者可以根据项目的具体需求来定制状态管理的行为,从而获得更高的灵活性和可扩展性。

总的来说,Zustand 通过其简单、高效和与 React 紧密集成的特性,为 React 应用程序的状态管理提供了一个优秀的解决方案。它的易用性、性能优化、中间件支持和良好的调试体验使其成为了许多开发者在构建 React 应用程序时的首选状态管理库。

如何使用Zustand

1. 安装 Zustand

首先,你需要安装 Zustand 库。可以通过 npm 或 yarn 来安装:

npm install zustand
# 或者
yarn add zustand

2. 创建一个 store

使用 create 方法创建一个新的 Zustand 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 })),
}))

3. 在组件中使用 store

在你的 React 组件中,使用 useStore 钩子来访问和更新 store 中的状态。

import { useStore } from './store'

function Counter() {
  const { count, increment, decrement } = useStore()

  return (
    <div>
      <h2>Counter: {count}</h2>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  )
)

高级特性

使用中间件

Zustand 支持中间件,你可以使用它来处理异步操作、实现不可变性等。

import create from 'zustand'
import { immer } from 'immer'

const useStore = create(
  immer(set => ({
    items: [],
    addItem: (item) => set(produce((draft) => { draft.items.push(item) })),
  })),
  { middleware: [immer] }
)

与 React Context 集成

Zustand 可以与 React Context 集成,使得在组件树中共享状态更加容易。

import { createContext, useContext } from 'react'
import { useStore } from './store'

const StoreContext = createContext(null)

function App() {
  const store = useStore()
  return (
    <StoreContext.Provider value={store}>
      {/* 应用程序的其他部分 */}
    </StoreContext.Provider>
  )
}

function Component() {
  const store = useContext(StoreContext)
  // 使用 store ...
}

监听状态变化

你可以订阅 store 的变化,以便在状态变化时执行某些操作。

const unsubscribe = useStore.subscribe(() => {
  console.log('State changed!')
})

// 当不再需要监听时,取消订阅
unsubscribe()

清理和销毁 store

在某些情况下,你可能需要清理或销毁 store。Zustand 提供了 destroy 方法来实现这一点。

const store = useStore()
// 当组件卸载时,清理 store
store.destroy()

使用自定义钩子

你可以创建自定义钩子来封装 store 的某些操作,使得在组件中使用更加方便。

const useIncrement = () => useStore(state => state.increment)

function Button() {
  const increment = useIncrement()
  return <button onClick={increment}>Increment</button>
}

处理异步操作

Zustand 允许你处理异步操作,并在操作完成后更新状态。

const useStore = create(set => ({
  data: null,
  loading: false,
  error: null,
  fetchData: async () => {
    set(state => ({ loading: true }))
    try {
      const response = await fetch('/api/data')
      const data = await response.json()
      set(state => ({ data, loading: false }))
    } catch (error) {
      set(state => ({ error, loading: false }))
    }
  },
}))

通过这些基本步骤和高级特性,可以开始在 React 应用程序中使用 Zustand 来管理状态。

Zustand 的设计旨在提供一种简单、高效且易于理解的方式来处理状态,无论是对于新手还是有经验的开发者,都是一个很好的状态管理库。

我的上一篇文章两种最简单的方式教会你如何实现前端一键换肤!其实可以使用状态管理来管理全局的主题样式,然后再配合zustand的持久化插件persist来实现一键换肤的功能,这样刷新之后也不会丢失状态了

persist持久化的用法

Zustand 的持久化插件是一个强大的功能,它允许你将状态保存在客户端的 localStoragesessionStorage 中。这意味着即使在页面刷新或关闭后,状态也能够被保留和恢复。这个功能对于那些需要持久保存用户操作的场景非常有用,比如表单数据、用户偏好设置等。

如何使用持久化插件

要使用 Zustand 的持久化功能,你需要先从 zustand 库中导入 persist 中间件。然后,你可以将这个中间件应用到你的 store 创建函数中。

以下是一个简单的例子,展示了如何使用 persist 中间件来持久化一个 store 中的状态:

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

// 定义你的 store 结构和操作
const useSettingsStore = create(
  persist(
    (set) => ({
      theme: 'light',
      setTheme: (theme) => set((state) => ({ theme })),
    }),
    {
      // 持久化配置项
      key: 'settings', // localStorage 中的 key 值
      whitelist: ['theme'], // 只持久化 theme 状态
      blacklist: [], // 不持久化任何状态
      debug: false, // 是否在控制台输出调试信息
    }
  )
)

// 现在你可以在组件中使用 useSettingsStore 钩子来访问和修改状态
// 状态变化后,它将自动保存到 localStorage 中

在上面的代码中,我们创建了一个名为 useSettingsStore 的 store,其中包含一个 theme 状态和一个 setTheme 操作。我们使用 persist 中间件来持久化这个 store,并设置了 key'settings',这样 localStorage 中就会有一个与之对应的键值对。

持久化配置项

persist 中间件接受一个配置对象,你可以在这个对象中定义持久化的行为:

  • key: 存储在 localStoragesessionStorage 中的键名。
  • whitelist: 一个数组,指定哪些状态应该被持久化。只有包含在数组中的状态才会被保存。
  • blacklist: 一个数组,指定哪些状态不应该被持久化。这是一个取反的 whitelist
  • debug: 一个布尔值,如果设置为 true,则会在控制台输出额外的调试信息。

自定义持久化中间件

如果你需要更细粒度的控制或者想要创建自己的持久化逻辑,你可以通过创建自定义中间件来实现。例如,你可以创建一个中间件来处理特定的存储逻辑或者在持久化前后执行额外的操作。

const myCustomPersist = (set, get, store) => {
  // 自定义持久化逻辑
  const originalSet = store.setState
  store.setState = (update, ...args) => {
    // 在更新状态之前或之后执行一些操作
    const result = originalSet(update, ...args)
    // 持久化状态
    // ...
    return result
  }
}

// 使用自定义持久化中间件
const useCustomStore = create(
  myCustomPersist(
    set => ({
      // 状态和操作
    })
  )
)

通过使用 Zustand 的持久化插件,你可以轻松地将状态保存在客户端存储中,从而提供更好的用户体验和更健壮的应用程序状态管理。这个功能特别适用于那些需要跨会话或页面刷新保持状态的场景。

总结

以上就是zustand的全部用法了。已经简单阐述了一下为什么要选zustand而不是继续用redux。

原文链接:https://juejin.cn/post/7352100456333885450 作者:前端少年汪

(0)
上一篇 2024年4月1日 上午11:08
下一篇 2024年4月1日 上午11:19

相关推荐

发表回复

登录后才能评论