首頁 >web前端 >js教程 >Zustand,何時、如何以及為何

Zustand,何時、如何以及為何

PHPz
PHPz原創
2024-09-03 21:00:40703瀏覽

目錄

  1. 狀態管理簡介
  2. 了解 Zustand
  3. 狀態類型
  4. 開始使用 Zustand
  5. Zustand 的主要特點
  6. 實作 Zustand
  7. Zustand 與其他狀態管理解決方案
  8. Zustand系統設計
  9. 使用 Zustand 保持狀態
  10. 在 React 元件之外使用 Zustand
  11. 現實世界的例子
  12. 結論
  13. 提示:使用 Zustand 處理非同步程式碼

1. 狀態管理簡介

狀態管理是現代 Web 開發的重要方面,尤其是在複雜的應用程式中。它涉及處理可能隨時間變化的數據,並確保該數據在整個應用程式中一致表示。有效的狀態管理可以提高應用程式的可預測性和可維護性。

2. 了解 Zustand

Zustand 是一個小型、快速且可擴展的 React 應用程式狀態管理解決方案。 Zustand 由 Jared Palmer 和 Daishi Kato 創建,提供了一個簡單直觀的 API,與其他解決方案相比,使狀態管理變得不那麼麻煩。

3. 國家類型

在深入了解 Zustand 之前,讓我們先了解一下 Web 應用程式中不同類型的狀態:

  1. 本地狀態:特定於組件的狀態,不需要與應用程式的其他部分共用。
  2. 全域狀態:需要由應用程式中的多個元件存取和修改的狀態。
  3. 遠端狀態:表示從外部來源(通常是 API)取得資料的狀態。

Zustand 擅長管理本地和全域狀態,並且可以與遠端狀態管理解決方案整合。

4. Zustand 入門

要開始使用 Zustand,先透過 npm、yarn 或 pnpm 安裝它:

npm install zustand
# or
yarn add zustand
# or
pnpm add zustand

5. Zustand的主要特點

Zustand 具有多項使其脫穎而出的功能:

  1. 簡單:Zustand 擁有最小的 API,使其易於學習和使用。
  2. 沒有樣板:與其他一些狀態管理解決方案不同,Zustand 需要很少的設定程式碼。
  3. 基於 Hooks:Zustand 利用 React Hooks,使其感覺適合現代 React 開發。
  4. TypeScript 支援:Zustand 與 TypeScript 配合得很好,提供出色的類型推斷。
  5. 中間件支援:Zustand 讓您透過中間件擴充其功能。
  6. Devtools 支援:Zustand 與 Redux DevTools 整合良好以進行偵錯。
  7. 與框架無關:雖然主要與 React 一起使用,但 Zustand 可以在任何 JavaScript 環境中使用。

6. 實施 Zustand

讓我們來看看 Zustand 的基本實作:

import { create } from 'zustand'

const useStore = create((set) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 }),
}))

function BearCounter() {
  const bears = useStore((state) => state.bears)
  return <h1>{bears} around here...</h1>
}

function Controls() {
  const increasePopulation = useStore((state) => state.increasePopulation)
  return <button onClick={increasePopulation}>one up</button>
}

在此範例中,我們建立一個具有熊狀態的商店和兩個修改它的操作。然後,BearCounter 和 Controls 元件可以使用 useStore 鉤子存取和修改狀態。

7. Zustand 與其他狀態管理解決方案

讓我們將 Zustand 與其他流行的狀態管理解決方案進行比較:

Zustand 與 Redux

Zustand 的優點:

  • 更簡單的 API,更少的樣板檔案
  • 不需要動作創建者或 switch 語句
  • 較小的捆綁尺寸

缺點:

  • 尚未建立的生態系
  • 更少的中間件選項

Zustand 與 MobX

Zustand 的優點:

  • 更簡單、更少神奇的 API
  • 大型應用程式的更好效能

缺點:

  • 預設反應性較低
  • 沒有開箱即用的計算值

Zustand 與 Recoil

Zustand 的優點:

  • 更簡單的心智模式
  • 在 React 之外工作

缺點:

  • 顆粒反應性較小
  • 沒有內建原子族概念

八、Zustand系統設計

Zustand 的系統設計是基於幾個關鍵原則:

  1. Single store: Zustand encourages the use of a single store for all application state.
  2. Immutability: State updates are handled immutably, ensuring predictable behavior.
  3. Subscriptions: Components subscribe to specific parts of the state, re-rendering only when those parts change.
  4. Middleware: Zustand uses a middleware system for extending functionality.

This design allows Zustand to be both simple and powerful, providing excellent performance even in large applications.

9. Persisting State with Zustand

Zustand makes it easy to persist state, which is crucial for many applications. Here's an example using the persist middleware:

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

const useStore = create(persist(
  (set, get) => ({
    fishes: 0,
    addAFish: () => set({ fishes: get().fishes + 1 }),
  }),
  {
    name: 'food-storage', // unique name
    getStorage: () => localStorage, // (optional) by default, 'localStorage' is used
  }
))

This will automatically save the state to localStorage and rehydrate it when the app reloads.

10. Using Zustand Outside React Components

One of Zustand's strengths is that it can be used outside of React components. This is particularly useful for integrating with other parts of your application or for testing:

const { getState, setState } = useStore

// Getting state
console.log(getState().bears)

// Setting state
setState({ bears: 10 })

// Using actions
getState().increasePopulation()

11. Real-World Examples

Let's look at some real-world examples of using Zustand:

Authentication State

import { create } from 'zustand'

const useAuthStore = create((set) => ({
  user: null,
  isAuthenticated: false,
  login: (userData) => set({ user: userData, isAuthenticated: true }),
  logout: () => set({ user: null, isAuthenticated: false }),
}))

// Usage in a component
function LoginButton() {
  const { isAuthenticated, login, logout } = useAuthStore()

  const handleAuth = () => {
    if (isAuthenticated) {
      logout()
    } else {
      // Simulate login
      login({ id: 1, name: 'John Doe' })
    }
  }

  return (
    <button onClick={handleAuth}>
      {isAuthenticated ? 'Logout' : 'Login'}
    </button>
  )
}

Shopping Cart

import { create } from 'zustand'

const useCartStore = create((set) => ({
  items: [],
  addItem: (item) => set((state) => ({ items: [...state.items, item] })),
  removeItem: (itemId) => set((state) => ({
    items: state.items.filter((item) => item.id !== itemId),
  })),
  clearCart: () => set({ items: [] }),
  total: 0,
  updateTotal: () => set((state) => ({
    total: state.items.reduce((sum, item) => sum + item.price, 0),
  })),
}))

// Usage in components
function CartSummary() {
  const { items, total, removeItem } = useCartStore()

  return (
    <div>
      {items.map((item) => (
        <div key={item.id}>
          {item.name} - ${item.price}
          <button onClick={() => removeItem(item.id)}>Remove</button>
        </div>
      ))}
      <div>Total: ${total}</div>
    </div>
  )
}

Theme Switcher

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

const useThemeStore = create(persist(
  (set) => ({
    theme: 'light',
    toggleTheme: () => set((state) => ({
      theme: state.theme === 'light' ? 'dark' : 'light',
    })),
  }),
  {
    name: 'theme-storage',
  }
))

// Usage in a component
function ThemeToggle() {
  const { theme, toggleTheme } = useThemeStore()

  return (
    <button onClick={toggleTheme}>
      Switch to {theme === 'light' ? 'dark' : 'light'} mode
    </button>
  )
}

12. Conclusion

Zustand offers a refreshing approach to state management in React applications. Its simplicity, flexibility, and performance make it an excellent choice for both small and large projects. By reducing boilerplate and providing a straightforward API, Zustand allows developers to focus on building features rather than managing complex state logic.

While it may not have the extensive ecosystem of some older state management solutions, Zustand's design principles and ease of use make it a compelling option for modern React development. Its ability to work outside of React components and easy integration with persistence solutions further extend its utility.

For many React applications, Zustand strikes an excellent balance between simplicity and power, making it worth considering for your next project.

Bonus tips:

Zustand also handles asynchronous functions/code really well and without the need for any Middleware setup.

Let's talk a bit about that:

13. Handling Asynchronous Code with Zustand

One of Zustand's strengths is its simplicity in handling asynchronous operations without the need for additional middleware or complex setups. This makes it particularly easy to work with API calls, data fetching, and other asynchronous tasks.

How Zustand Handles Asynchronous Code

Zustand's approach to asynchronous code is straightforward:

  1. Direct Integration: Asynchronous functions can be defined directly in the store.
  2. No Special Syntax: You don't need to use special action creators or thunks.
  3. State Updates: You can update the state within async functions using the set function.
  4. Error Handling: Error states can be managed directly within the async functions.

Implementing Asynchronous Code

Here's an example of how to implement asynchronous code in Zustand:

import { create } from 'zustand'

const useUserStore = create((set) => ({
  user: null,
  isLoading: false,
  error: null,
  fetchUser: async (userId) => {
    set({ isLoading: true, error: null });
    try {
      const response = await fetch(`https://api.example.com/users/${userId}`);
      if (!response.ok) throw new Error('Failed to fetch user');
      const userData = await response.json();
      set({ user: userData, isLoading: false });
    } catch (error) {
      set({ error: error.message, isLoading: false });
    }
  },
}));

// Usage in a component
function UserProfile({ userId }) {
  const { user, isLoading, error, fetchUser } = useUserStore();

  React.useEffect(() => {
    fetchUser(userId);
  }, [userId]);

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  if (!user) return null;

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
    </div>
  );
}

In this example:

  1. We define an async fetchUser function directly in the store.
  2. The function manages loading and error states alongside the user data.
  3. We use the set function to update the state at different points in the async operation.
  4. In the component, we can use the store's state and actions as usual, with React hooks handling the component lifecycle.

Benefits of Zustand's Approach to Async Code

  1. Simplicity: No need for additional middleware or complex action creators.
  2. Flexibility: You can structure your async logic however you prefer.
  3. Readability: Async operations are defined close to the relevant state.
  4. Easy Testing: Async functions can be easily unit tested.

Comparison with Other Solutions

Unlike Redux, which often requires middleware like Redux Thunk or Redux Saga for handling async operations, Zustand's approach is much more straightforward. This simplicity can lead to less boilerplate and a gentler learning curve, especially for developers new to state management.

MobX and Recoil also offer ways to handle async operations, but Zustand's approach might be considered more intuitive due to its direct use of async/await syntax without additional abstractions.

異步的結論

Zustand 對非同步程式碼的處理體現了其簡單性和靈活性的理念。透過允許開發人員直接在儲存中編寫非同步函數,無需特殊語法或中間件,Zustand 可以輕鬆管理複雜的狀態操作,同時保持程式碼庫乾淨和可讀。

這種非同步程式碼方法,與 Zustand 的其他功能(如小套件大小和易於設定)相結合,使其成為各種規模的專案的絕佳選擇,特別是那些涉及重要非同步狀態管理的專案。

希望這個「有點指南」對任何正在思考如何管理全域應用程式狀態的人來說都是有用且富有洞察力的。
謝謝您,祝您編碼愉快。

看我的網站 https://www.ricardogesteves.com

跟著我@ricardogesteves
X(推特)

Zustand, When, how and why

RicardoGEsteves (里卡多·埃斯特維斯) · GitHub

全端開發人員 |熱衷於創造直覺且有影響力的使用者體驗 |總部位於葡萄牙里斯本? - 里卡多·GE史蒂夫斯

Zustand, When, how and why github.com

以上是Zustand,何時、如何以及為何的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn