ズスタンド、いつ、どのように、そしてなぜ

PHPz
リリース: 2024-09-03 21:00:40
オリジナル
655 人が閲覧しました

目次

  1. 状態管理の概要
  2. ズスタンドを理解する
  3. 状態の種類
  4. Zustand を始める
  5. Zustand の主な機能
  6. Zustand の実装
  7. Zustand と他の状態管理ソリューションの比較
  8. Zustandのシステム設計
  9. Zustand による状態の永続化
  10. React コンポーネントの外部で Zustand を使用する
  11. 実際の例
  12. 結論
  13. ヒント: Zustand を使用した非同期コードの処理

1. 状態管理の概要

状態管理は、最新の Web 開発、特に複雑なアプリケーションにおいて重要な側面です。これには、時間の経過とともに変化する可能性のあるデータを処理し、このデータがアプリケーション全体で一貫して表現されるようにすることが含まれます。効果的な状態管理は、アプリケーションの予測可能性と保守性の向上につながります。

2. ズスタンドを理解する

Zustand は、React アプリケーション向けの小型、高速、スケーラブルな状態管理ソリューションです。 Jared Palmer と Daishi Kata によって作成された Zustand は、他のソリューションに比べて状態管理の煩雑さを軽減する、シンプルで直感的な 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. フックベース: Zustand は React Hook を活用し、最新の React 開発にネイティブな感じを与えます。
  4. TypeScript のサポート: Zustand は TypeScript とうまく連携し、優れた型推論を提供します。
  5. ミドルウェアのサポート: Zustand では、ミドルウェアを通じて機能を拡張できます。
  6. Devtools のサポート: Zustand は、デバッグのために Redux DevTools と適切に統合されます。
  7. フレームワークに依存しない: Zustand は主に React で使用されますが、あらゆる 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>
}
ログイン後にコピー

この例では、bears 状態とそれを変更する 2 つのアクションを持つストアを作成します。 BearCounter コンポーネントと Controls コンポーネントは、useStore フックを使用して状態にアクセスし、変更できるようになります。

7. Zustand と他の状態管理ソリューションの比較

Zustand を他の一般的な状態管理ソリューションと比較してみましょう:

Zustand 対 Redux

Zustand の長所:

  • 定型文が少なくシンプルな API
  • アクション クリエーターや switch ステートメントは必要ありません
  • バンドル サイズが小さくなります

短所:

  • 確立されていないエコシステム
  • ミドルウェアのオプションが少ない

ズスタンド vs. MobX

Zustand の長所:

  • より簡単で、魔法が少なくなった API
  • 大規模なアプリケーションのパフォーマンスの向上

短所:

  • デフォルトでは反応性が低くなります
  • そのままでは計算値はありません

ズスタンド vs リコイル

Zustand の長所:

  • より単純なメンタルモデル
  • React の外部で動作します

短所:

  • 粒度の低い反応性
  • 原子ファミリーの概念は組み込まれていません

8. 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

フルスタック開発者 |直感的でインパクトのあるユーザー エクスペリエンスの作成に情熱を注ぐ |ポルトガルのリスボンに拠点を置く?? - リカルド・ジェスティーブス

Zustand, When, how and why github.com

以上がズスタンド、いつ、どのように、そしてなぜの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!