Zustand チュートリアル

チュートリアルの概要

包括的な Zustand チュートリアルへようこそ!このガイドでは、初心者から上級者まで、Zustand による状態管理について知っておくべきすべてのことを教えます。

レッスン 1: Zustand の紹介

Zustand は、以下を提供する React 用の軽量な状態管理ライブラリです:

  • シンプルで直感的な API
  • ボイラープレートコード不要
  • 優れた TypeScript サポート
  • 自動最適化による優れたパフォーマンス
  • 小さなバンドルサイズ(1KB 未満)

なぜ Zustand を選ぶのか?

Redux や MobX などの他の状態管理ソリューションと比較して、Zustand は強力な機能と優れたパフォーマンスを維持しながら、ボイラープレートの少ないシンプルな API を提供します。

レッスン 2: 最初のストアを作成する

シンプルな ToDo リストアプリケーションを作成しましょう:

import { create } from 'zustand'

interface Todo {
  id: number
  text: string
  completed: boolean
}

interface TodoStore {
  todos: Todo[]
  addTodo: (text: string) => void
  toggleTodo: (id: number) => void
  removeTodo: (id: number) => void
}

const useTodoStore = create<TodoStore>((set) => ({
  todos: [],
  addTodo: (text) =>
    set((state) => ({
      todos: [
        ...state.todos,
        { id: Date.now(), text, completed: false }
      ]
    })),
  toggleTodo: (id) =>
    set((state) => ({
      todos: state.todos.map((todo) =>
        todo.id === id
          ? { ...todo, completed: !todo.completed }
          : todo
      )
    })),
  removeTodo: (id) =>
    set((state) => ({
      todos: state.todos.filter((todo) => todo.id !== id)
    })),
}))

Lesson 3: Using the Store in Components

function TodoList() {
  const todos = useTodoStore((state) => state.todos)
  const addTodo = useTodoStore((state) => state.addTodo)
  const toggleTodo = useTodoStore((state) => state.toggleTodo)
  const removeTodo = useTodoStore((state) => state.removeTodo)
  const [input, setInput] = useState('')

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault()
    if (input.trim()) {
      addTodo(input)
      setInput('')
    }
  }

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Add a todo..."
        />
        <button type="submit">Add</button>
      </form>
      
      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
            />
            <span style={{ 
              textDecoration: todo.completed ? 'line-through' : 'none' 
            }}>
              {todo.text}
            </span>
            <button onClick={() => removeTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  )
}

レッスン 4: 非同期アクションと高度なパターン

非同期アクション

Zustand での非同期アクションの処理は簡単です - アクションを async にするだけです!

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')
      const data = await response.json()
      set({ data, loading: false })
    } catch (error) {
      set({ error: error.message, loading: false })
    }
  }
}))

計算された値

セレクターを使用して派生状態を作成します:

const useStore = create((set) => ({
  todos: [],
  // ... actions
}))

// In your component
const completedCount = useStore(
  (state) => state.todos.filter(t => t.completed).length
)
const totalCount = useStore((state) => state.todos.length)

次のステップ

これらのトピックで学習を続けましょう:

  • 永続化と DevTools のためのミドルウェア
  • Zustand ストアのテスト
  • 高度な TypeScript パターン
  • パフォーマンス最適化テクニック
  • 他のライブラリとの統合