Elysia Tools

Parcourez outils, exemples, explications visuelles et guides thématiques dans un espace clair.

Catégories populaires

Dossiers

Langue
ZHESPTRUFRDEEN

Elysia Tools

Navigation mobile

Gestion d'état

Exemples Zustand

Exemples de la bibliothèque de gestion d'état Zustand incluant la configuration de base, middleware, persistance et patterns avancés

Exemples

Entrées de cette collection

Code sourcetypescriptSimple

Store de Base Zustand

Patterns fondamentaux de store Zustand incluant créer, mettre à jour et consommer l'état dans les composants React

Difficulté

3/10

Temps estimé

20 min

Étiquettes

zustand, state-management, react, typescript

Prérequis

React basics, TypeScript, Hooks

typescript
// Zustand Basic Store Examples
// Zustand is a small, fast, and scalable state management solution for React

// 1. Basic Counter Store
import React, { useState, useEffect, useCallback } from 'react'
import { create } from 'zustand'

interface CounterState {
  count: number
  increment: () => void
  decrement: () => void
  reset: () => void
}

const useCounterStore = create<CounterState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}))

// Usage in component
function Counter() {
  const { count, increment, decrement, reset } = useCounterStore()

  return (
    <div className="p-4 border rounded-lg">
      <h2 className="text-xl font-bold mb-4">Counter: {count}</h2>
      <div className="space-x-2">
        <button onClick={increment} className="px-4 py-2 bg-blue-500 text-white rounded">
          Increment
        </button>
        <button onClick={decrement} className="px-4 py-2 bg-red-500 text-white rounded">
          Decrement
        </button>
        <button onClick={reset} className="px-4 py-2 bg-gray-500 text-white rounded">
          Reset
        </button>
      </div>
    </div>
  )
}

// 2. Todo Store with CRUD Operations
interface Todo {
  id: string
  text: string
  completed: boolean
  createdAt: Date
}

interface TodoState {
  todos: Todo[]
  addTodo: (text: string) => void
  toggleTodo: (id: string) => void
  deleteTodo: (id: string) => void
  updateTodo: (id: string, text: string) => void
  clearCompleted: () => void
  completedCount: number
  totalCount: number
}

const useTodoStore = create<TodoState>((set, get) => ({
  todos: [],
  addTodo: (text: string) => {
    const newTodo: Todo = {
      id: Date.now().toString(),
      text,
      completed: false,
      createdAt: new Date(),
    }
    set((state) => ({ todos: [...state.todos, newTodo] }))
  },
  toggleTodo: (id: string) =>
    set((state) => ({
      todos: state.todos.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      ),
    })),
  deleteTodo: (id: string) =>
    set((state) => ({
      todos: state.todos.filter((todo) => todo.id !== id),
    })),
  updateTodo: (id: string, text: string) =>
    set((state) => ({
      todos: state.todos.map((todo) =>
        todo.id === id ? { ...todo, text } : todo
      ),
    })),
  clearCompleted: () =>
    set((state) => ({
      todos: state.todos.filter((todo) => !todo.completed),
    })),
  get completedCount() {
    return get().todos.filter((todo) => todo.completed).length
  },
  get totalCount() {
    return get().todos.length
  },
}))

// Todo Component
function TodoList() {
  const {
    todos,
    addTodo,
    toggleTodo,
    deleteTodo,
    updateTodo,
    clearCompleted,
    completedCount,
    totalCount,
  } = useTodoStore()

  const [newTodoText, setNewTodoText] = useState('')

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

  return (
    <div className="max-w-md mx-auto p-4">
      <h1 className="text-2xl font-bold mb-4">Todo List</h1>

      <form onSubmit={handleSubmit} className="mb-4">
        <div className="flex space-x-2">
          <input
            type="text"
            value={newTodoText}
            onChange={(e) => setNewTodoText(e.target.value)}
            placeholder="Add a new todo..."
            className="flex-1 px-3 py-2 border rounded"
          />
          <button type="submit" className="px-4 py-2 bg-blue-500 text-white rounded">
            Add
          </button>
        </div>
      </form>

      <div className="mb-4 text-sm text-gray-600">
        {completedCount} of {totalCount} completed
      </div>

      <ul className="space-y-2">
        {todos.map((todo) => (
          <li key={todo.id} className="flex items-center space-x-2">
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
              className="w-4 h-4"
            />
            <input
              type="text"
              value={todo.text}
              onChange={(e) => updateTodo(todo.id, e.target.value)}
              className={`flex-1 px-2 py-1 border rounded ${
                todo.completed ? 'line-through text-gray-500' : ''
              }`}
            />
            <button
              onClick={() => deleteTodo(todo.id)}
              className="px-2 py-1 bg-red-500 text-white rounded text-sm"
            >
              Delete
            </button>
          </li>
        ))}
      </ul>

      {completedCount > 0 && (
        <button
          onClick={clearCompleted}
          className="mt-4 px-4 py-2 bg-gray-500 text-white rounded"
        >
          Clear Completed ({completedCount})
        </button>
      )}
    </div>
  )
}

// 3. Shopping Cart Store
interface CartItem {
  id: string
  name: string
  price: number
  quantity: number
  image?: string
}

interface CartState {
  items: CartItem[]
  addItem: (item: Omit<CartItem, 'quantity'>) => void
  removeItem: (id: string) => void
  updateQuantity: (id: string, quantity: number) => void
  clearCart: () => void
  getTotalPrice: () => number
  getTotalItems: () => number
  isInCart: (id: string) => boolean
}

const useCartStore = create<CartState>((set, get) => ({
  items: [],
  addItem: (item) =>
    set((state) => {
      const existingItem = state.items.find((i) => i.id === item.id)
      if (existingItem) {
        return {
          items: state.items.map((i) =>
            i.id === item.id
              ? { ...i, quantity: i.quantity + 1 }
              : i
          ),
        }
      }
      return { items: [...state.items, { ...item, quantity: 1 }] }
    }),
  removeItem: (id) =>
    set((state) => ({
      items: state.items.filter((item) => item.id !== id),
    })),
  updateQuantity: (id, quantity) =>
    set((state) => ({
      items: state.items.map((item) =>
        item.id === id ? { ...item, quantity: Math.max(1, quantity) } : item
      ),
    })),
  clearCart: () => set({ items: [] }),
  getTotalPrice: () =>
    get().items.reduce((total, item) => total + item.price * item.quantity, 0),
  getTotalItems: () =>
    get().items.reduce((total, item) => total + item.quantity, 0),
  isInCart: (id) => get().items.some((item) => item.id === id),
}))

// Cart Component
function ShoppingCart() {
  const {
    items,
    addItem,
    removeItem,
    updateQuantity,
    clearCart,
    getTotalPrice,
    getTotalItems,
  } = useCartStore()

  const sampleProducts = [
    { id: '1', name: 'Laptop', price: 999, image: '/laptop.jpg' },
    { id: '2', name: 'Mouse', price: 29, image: '/mouse.jpg' },
    { id: '3', name: 'Keyboard', price: 79, image: '/keyboard.jpg' },
  ]

  return (
    <div className="max-w-4xl mx-auto p-4">
      <h1 className="text-2xl font-bold mb-6">Shopping Cart</h1>

      <div className="grid md:grid-cols-2 gap-8">
        {/* Products */}
        <div>
          <h2 className="text-xl font-semibold mb-4">Products</h2>
          <div className="space-y-4">
            {sampleProducts.map((product) => (
              <div key={product.id} className="border p-4 rounded-lg">
                <div className="flex justify-between items-start">
                  <div>
                    <h3 className="font-semibold">{product.name}</h3>
                    <p className="text-gray-600">${product.price}</p>
                  </div>
                  <button
                    onClick={() => addItem(product)}
                    className="px-3 py-1 bg-blue-500 text-white rounded"
                  >
                    Add to Cart
                  </button>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* Cart */}
        <div>
          <h2 className="text-xl font-semibold mb-4">
            Cart ({getTotalItems()} items)
          </h2>

          {items.length === 0 ? (
            <p className="text-gray-500">Your cart is empty</p>
          ) : (
            <>
              <div className="space-y-2 mb-4">
                {items.map((item) => (
                  <div key={item.id} className="border p-3 rounded">
                    <div className="flex justify-between items-center">
                      <div>
                        <h4 className="font-semibold">{item.name}</h4>
                        <p className="text-gray-600">${item.price}</p>
                      </div>
                      <div className="flex items-center space-x-2">
                        <input
                          type="number"
                          min="1"
                          value={item.quantity}
                          onChange={(e) => {
                            const nextQuantity = Number(e.target.value)
                            updateQuantity(item.id, Number.isFinite(nextQuantity) ? nextQuantity : 1)
                          }}
                          className="w-16 px-2 py-1 border rounded"
                        />
                        <button
                          onClick={() => removeItem(item.id)}
                          className="px-2 py-1 bg-red-500 text-white rounded text-sm"
                        >
                          Remove
                        </button>
                      </div>
                    </div>
                    <p className="text-sm text-gray-600 mt-1">
                      Subtotal: ${(item.price * item.quantity).toFixed(2)}
                    </p>
                  </div>
                ))}
              </div>

              <div className="border-t pt-4">
                <div className="flex justify-between text-lg font-semibold">
                  <span>Total:</span>
                  <span>${getTotalPrice().toFixed(2)}</span>
                </div>
                <div className="mt-4 space-x-2">
                  <button className="px-4 py-2 bg-green-500 text-white rounded">
                    Checkout
                  </button>
                  <button
                    onClick={clearCart}
                    className="px-4 py-2 bg-gray-500 text-white rounded"
                  >
                    Clear Cart
                  </button>
                </div>
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  )
}

// 4. User Authentication Store
interface User {
  id: string
  name: string
  email: string
  avatar?: string
  role: 'admin' | 'user'
}

interface AuthState {
  user: User | null
  isAuthenticated: boolean
  isLoading: boolean
  login: (email: string, password: string) => Promise<void>
  logout: () => void
  register: (name: string, email: string, password: string) => Promise<void>
  updateProfile: (data: Partial<User>) => Promise<void>
}

const useAuthStore = create<AuthState>((set, get) => ({
  user: null,
  isAuthenticated: false,
  isLoading: false,

  login: async (email: string, password: string) => {
    set({ isLoading: true })
    try {
      // Simulate API call
      await new Promise((resolve) => setTimeout(resolve, 1000))

      // Mock successful login
      const user: User = {
        id: '1',
        name: 'John Doe',
        email,
        role: 'user',
        avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e',
      }

      set({ user, isAuthenticated: true, isLoading: false })
    } catch (error) {
      set({ isLoading: false })
      throw error
    }
  },

  logout: () => {
    set({ user: null, isAuthenticated: false })
  },

  register: async (name: string, email: string, password: string) => {
    set({ isLoading: true })
    try {
      // Simulate API call
      await new Promise((resolve) => setTimeout(resolve, 1000))

      const user: User = {
        id: Date.now().toString(),
        name,
        email,
        role: 'user',
      }

      set({ user, isAuthenticated: true, isLoading: false })
    } catch (error) {
      set({ isLoading: false })
      throw error
    }
  },

  updateProfile: async (data: Partial<User>) => {
    const currentUser = get().user
    if (!currentUser) return

    try {
      // Simulate API call
      await new Promise((resolve) => setTimeout(resolve, 500))

      const updatedUser = { ...currentUser, ...data }
      set({ user: updatedUser })
    } catch (error) {
      throw error
    }
  },
}))

// Authentication Components
function LoginForm() {
  const { login, isLoading } = useAuthStore()
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    try {
      await login(email, password)
    } catch (error) {
      alert('Login failed')
    }
  }

  return (
    <form onSubmit={handleSubmit} className="max-w-md mx-auto p-4">
      <h2 className="text-xl font-bold mb-4">Login</h2>
      <div className="space-y-4">
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="Email"
          className="w-full px-3 py-2 border rounded"
          required
        />
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="Password"
          className="w-full px-3 py-2 border rounded"
          required
        />
        <button
          type="submit"
          disabled={isLoading}
          className="w-full px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
        >
          {isLoading ? 'Logging in...' : 'Login'}
        </button>
      </div>
    </form>
  )
}

function UserProfile() {
  const { user, logout, updateProfile } = useAuthStore()
  const [isEditing, setIsEditing] = useState(false)
  const [editName, setEditName] = useState(user?.name || '')

  const handleUpdate = async () => {
    try {
      await updateProfile({ name: editName })
      setIsEditing(false)
    } catch (error) {
      alert('Update failed')
    }
  }

  return (
    <div className="max-w-md mx-auto p-4">
      <h2 className="text-xl font-bold mb-4">Profile</h2>

      <div className="space-y-4">
        {user?.avatar && (
          <img
            src={user.avatar}
            alt={user.name}
            className="w-20 h-20 rounded-full"
          />
        )}

        <div>
          {isEditing ? (
            <div className="flex space-x-2">
              <input
                type="text"
                value={editName}
                onChange={(e) => setEditName(e.target.value)}
                className="flex-1 px-3 py-2 border rounded"
              />
              <button
                onClick={handleUpdate}
                className="px-3 py-2 bg-green-500 text-white rounded"
              >
                Save
              </button>
              <button
                onClick={() => setIsEditing(false)}
                className="px-3 py-2 bg-gray-500 text-white rounded"
              >
                Cancel
              </button>
            </div>
          ) : (
            <div>
              <p className="font-semibold">{user?.name}</p>
              <p className="text-gray-600">{user?.email}</p>
              <p className="text-sm text-gray-500">Role: {user?.role}</p>
              <button
                onClick={() => {
                  setEditName(user?.name || '')
                  setIsEditing(true)
                }}
                className="mt-2 px-3 py-1 bg-blue-500 text-white rounded text-sm"
              >
                Edit Profile
              </button>
            </div>
          )}
        </div>

        <button
          onClick={logout}
          className="px-4 py-2 bg-red-500 text-white rounded"
        >
          Logout
        </button>
      </div>
    </div>
  )
}
Code sourcetypescriptIntermédiaire

Patterns Avancés Zustand

Patterns complexes Zustand incluant middleware, persistance, sélecteurs et optimisation des performances

Difficulté

7/10

Temps estimé

40 min

Étiquettes

zustand, advanced, state-management, middleware

Prérequis

Zustand basics, React hooks, TypeScript, Testing fundamentals

typescript
// Advanced Zustand Patterns

// 1. Persistence with Middleware
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'

interface UserPreferences {
  theme: 'light' | 'dark'
  language: string
  notifications: boolean
  fontSize: 'small' | 'medium' | 'large'
}

const usePreferencesStore = create<UserPreferences>()(
  persist(
    (set) => ({
      theme: 'light',
      language: 'en',
      notifications: true,
      fontSize: 'medium',
      setTheme: (theme) => set({ theme }),
      setLanguage: (language) => set({ language }),
      toggleNotifications: () => set((state) => ({
        notifications: !state.notifications
      })),
      setFontSize: (fontSize) => set({ fontSize }),
    }),
    {
      name: 'user-preferences',
      storage: createJSONStorage(() => localStorage),
      partialize: (state) => ({
        theme: state.theme,
        language: state.language,
        fontSize: state.fontSize,
      }),
    }
  )
)

// 2. DevTools Middleware
import { devtools } from 'zustand/middleware'

interface AppStore {
  users: User[]
  posts: Post[]
  addUser: (user: User) => void
  addPost: (post: Post) => void
  removeUser: (id: string) => void
  removePost: (id: string) => void
}

const useAppStore = create<AppStore>()(
  devtools(
    (set) => ({
      users: [],
      posts: [],
      addUser: (user) => set((state) => ({
        users: [...state.users, user]
      })),
      addPost: (post) => set((state) => ({
        posts: [...state.posts, post]
      })),
      removeUser: (id) => set((state) => ({
        users: state.users.filter(user => user.id !== id)
      })),
      removePost: (id) => set((state) => ({
        posts: state.posts.filter(post => post.id !== id)
      })),
    }),
    {
      name: 'app-store',
      anonymousActionType: 'unknown',
    }
  )
)

// 3. Subscribe to Store Changes
const useLogger = () => {
  const subscribe = useAppStore.subscribe

  useEffect(() => {
    const unsubscribe = subscribe((state) => {
      console.log('Store updated:', state)
    })

    return unsubscribe
  }, [subscribe])
}

// Select specific state changes
useAppStore.subscribe(
  (state) => state.users,
  (users) => {
    console.log('Users changed:', users)
  }
)

// 4. Combining Multiple Stores
const useCombinedStore = () => {
  const preferences = usePreferencesStore()
  const cart = useCartStore()

  const getLocalizedPrice = (price: number) => {
    const formatter = new Intl.NumberFormat(preferences.language, {
      style: 'currency',
      currency: preferences.language === 'en' ? 'USD' : 'EUR',
    })
    return formatter.format(price)
  }

  return {
    ...preferences,
    ...cart,
    getLocalizedPrice,
  }
}

// 5. Async Actions with Error Handling
interface AsyncStore {
  data: any[]
  loading: boolean
  error: string | null
  fetchData: () => Promise<void>
  createItem: (item: any) => Promise<void>
  updateItem: (id: string, updates: any) => Promise<void>
  deleteItem: (id: string) => Promise<void>
  clearError: () => void
}

const useAsyncStore = create<AsyncStore>((set, get) => ({
  data: [],
  loading: false,
  error: null,

  clearError: () => set({ error: null }),

  fetchData: async () => {
    set({ loading: true, error: null })
    try {
      const response = await fetch('/api/data')
      const data = await response.json()
      set({ data, loading: false })
    } catch (error) {
      set({
        error: error instanceof Error ? error.message : 'Failed to fetch data',
        loading: false
      })
    }
  },

  createItem: async (item) => {
    set({ loading: true, error: null })
    try {
      const response = await fetch('/api/data', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(item),
      })
      const newItem = await response.json()

      set((state) => ({
        data: [...state.data, newItem],
        loading: false
      }))
    } catch (error) {
      set({
        error: error instanceof Error ? error.message : 'Failed to create item',
        loading: false
      })
    }
  },

  updateItem: async (id, updates) => {
    set({ loading: true, error: null })
    try {
      const response = await fetch(`/api/data/${id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(updates),
      })
      const updatedItem = await response.json()

      set((state) => ({
        data: state.data.map(item =>
          item.id === id ? { ...item, ...updatedItem } : item
        ),
        loading: false
      }))
    } catch (error) {
      set({
        error: error instanceof Error ? error.message : 'Failed to update item',
        loading: false
      })
    }
  },

  deleteItem: async (id) => {
    set({ loading: true, error: null })
    try {
      await fetch(`/api/data/${id}`, { method: 'DELETE' })

      set((state) => ({
        data: state.data.filter(item => item.id !== id),
        loading: false
      }))
    } catch (error) {
      set({
        error: error instanceof Error ? error.message : 'Failed to delete item',
        loading: false
      })
    }
  },
}))

// 6. Custom Selectors for Performance
const useGameStore = create<GameStore>()(
  devtools(
    persist(
      (set, get) => ({
        players: [],
        enemies: [],
        items: [],
        score: 0,
        level: 1,
        health: 100,

        // Actions
        addPlayer: (player) => set((state) => ({
          players: [...state.players, player]
        })),

        spawnEnemy: (enemy) => set((state) => ({
          enemies: [...state.enemies, enemy]
        })),

        collectItem: (item) => set((state) => ({
          items: [...state.items, item],
          score: state.score + item.points
        })),

        takeDamage: (damage) => set((state) => ({
          health: Math.max(0, state.health - damage)
        })),

        levelUp: () => set((state) => ({
          level: state.level + 1,
          health: state.health + 20
        })),
      }),
      {
        name: 'game-store',
        storage: createJSONStorage(() => localStorage),
      }
    )
  )
)

// Custom selectors with memoization
const useGameSelectors = () => {
  const store = useGameStore()

  const aliveEnemies = useStore(useCallback(
    (state) => state.enemies.filter(enemy => enemy.health > 0),
    []
  ))

  const playerHealth = useStore(useCallback(
    (state) => state.health,
    []
  ))

  const isGameOver = useStore(useCallback(
    (state) => state.health <= 0,
    []
  ))

  const highScore = useStore(useCallback(
    (state) => state.score,
    []
  ))

  return {
    aliveEnemies,
    playerHealth,
    isGameOver,
    highScore,
    ...store
  }
}

// 7. Optimistic Updates
interface OptimisticStore {
  posts: Post[]
  updatePostOptimistic: (id: string, updates: Partial<Post>) => Promise<void>
  deletePostOptimistic: (id: string) => Promise<void>
}

const useOptimisticStore = create<OptimisticStore>((set, get) => ({
  posts: [],

  updatePostOptimistic: async (id, updates) => {
    const previousPosts = get().posts

    // Optimistic update
    set((state) => ({
      posts: state.posts.map(post =>
        post.id === id ? { ...post, ...updates } : post
      )
    }))

    try {
      const response = await fetch(`/api/posts/${id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(updates),
      })

      if (!response.ok) {
        throw new Error('Update failed')
      }

      const updatedPost = await response.json()

      // Confirm update
      set((state) => ({
        posts: state.posts.map(post =>
          post.id === id ? updatedPost : post
        )
      }))
    } catch (error) {
      // Revert on error
      set({ posts: previousPosts })
      throw error
    }
  },

  deletePostOptimistic: async (id) => {
    const previousPosts = get().posts

    // Optimistic deletion
    set((state) => ({
      posts: state.posts.filter(post => post.id !== id)
    }))

    try {
      const response = await fetch(`/api/posts/${id}`, {
        method: 'DELETE',
      })

      if (!response.ok) {
        throw new Error('Delete failed')
      }
    } catch (error) {
      // Revert on error
      set({ posts: previousPosts })
      throw error
    }
  },
}))

// 8. Testing Zustand Stores
import { act, renderHook } from '@testing-library/react'
import { create } from 'zustand'

// Test store
interface TestStore {
  count: number
  increment: () => void
  decrement: () => void
}

const useTestStore = create<TestStore>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}))

// Test cases
describe('useTestStore', () => {
  it('should initialize with count 0', () => {
    const { result } = renderHook(() => useTestStore())
    expect(result.current.count).toBe(0)
  })

  it('should increment count', () => {
    const { result } = renderHook(() => useTestStore())

    act(() => {
      result.current.increment()
    })

    expect(result.current.count).toBe(1)
  })

  it('should decrement count', () => {
    const { result } = renderHook(() => useTestStore())

    act(() => {
      result.current.decrement()
    })

    expect(result.current.count).toBe(-1)
  })
})

// 9. TypeScript Best Practices
interface StrictStore {
  readonly state: {
    user: User | null
    status: 'idle' | 'loading' | 'success' | 'error'
  }
  actions: {
    setUser: (user: User) => void
    clearUser: () => void
    setStatus: (status: StrictStore['state']['status']) => void
  }
}

const useStrictStore = create<StrictStore>((set) => ({
  state: {
    user: null,
    status: 'idle' as const,
  },
  actions: {
    setUser: (user) =>
      set((state) => ({
        state: { ...state.state, user }
      })),
    clearUser: () =>
      set((state) => ({
        state: { ...state.state, user: null }
      })),
    setStatus: (status) =>
      set((state) => ({
        state: { ...state.state, status }
      })),
  },
}))

// Usage with destructuring
const { state: { user, status }, actions } = useStrictStore()

// 10. Server-Side Rendering Support
import { create } from 'zustand'
import { createContext, useContext, useRef } from 'react'

// Store interface
interface Store {
  count: number
  increment: () => void
}

// Create store
const createStore = () => create<Store>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}))

// Context for store
const StoreContext = createContext<ReturnType<typeof createStore> | null>(null)

// Provider component
export const StoreProvider = ({ children }: { children: React.ReactNode }) => {
  const storeRef = useRef<ReturnType<typeof createStore>>()

  if (!storeRef.current) {
    storeRef.current = createStore()
  }

  return (
    <StoreContext.Provider value={storeRef.current}>
      {children}
    </StoreContext.Provider>
  )
}

// Hook to use store
export const useStore = <T>(selector: (store: Store) => T): T => {
  const store = useContext(StoreContext)

  if (!store) {
    throw new Error('useStore must be used within StoreProvider')
  }

  return useStore(store, selector)
}

Outils

Outils souvent utilisés avec cet exemple

Associé

Collections d’exemples associées

Guide d'utilisation de l'outil

Contexte pour comprendre cette collection d’exemples

Titre

Exemples Zustand

Description

Exemples de la bibliothèque de gestion d'état Zustand incluant la configuration de base, middleware, persistance et patterns avancés

Aperçu

Exemples de la bibliothèque de gestion d'état Zustand incluant la configuration de base, middleware, persistance et patterns avancés

Quand l’utiliser

  • Use this sample set when you want reference inputs for Exemples Zustand.
  • Use it to preview output formats and compare related sample variants.

Fonctionnement

  1. 1Open a sample entry to inspect the prepared example payload or asset.
  2. 2Compare it with related tools to understand how the workflow connects.

Cas d’usage

  • Store de Base Zustand
  • Patterns Avancés Zustand

FAQ

What is included in Exemples Zustand?

This page includes curated sample entries, related tools, and neighboring sample collections for Exemples Zustand.

Accueil
Outils3197
Exemples593
Visualisations461
Visionneuses de fichiers103
Dossiers229
Étiquettes333
Images, audio et vidéo655

Outils de traitement, conversion et optimisation d’images, d’audio et de vidéo

Maths, dates et finance644

Calculateurs, outils numériques, logique de dates, statistiques et finance

Design et couleur296

Outils de couleur, mise en page, graphisme, style visuel et assistance design

Texte et rédaction209

Outils de rédaction, nettoyage, formatage, extraction et analyse de texte

Développement et Web193

Utilitaires développeur, réseau, débogage Web et assistants d’automatisation

Conversion et encodage175

Outils de conversion de formats, fichiers, archives, unités et encodages

Structurer une capture d'interface, la relire et la transmettre au développement
Esquisse au piano, contrôle MIDI et livraison d'une maquette d'écoute
Revue de textures rétro et remise des ressources
Revue et remise d’un guide opératoire illustré par captures
Revue visuelle d’une refonte responsive et remise des preuves

© 2026 Elysia Tools. Tous droits réservés.

DocumentationTarifsÀ proposConditions d'utilisationPolitique de confidentialitéCookiesContact