# Chapitre 2 : Gestion d'état SmartCommon propose plusieurs hooks pour gérer l'état selon les besoins : - **useGlobalStates** : état partagé entre composants avec persistance - **useStates** : état local d'un composant - **useForm** : état spécialisé pour les formulaires ## useGlobalStates État global accessible partout, avec persistance automatique. ### Syntaxe de base ```javascript import { useGlobalStates } from '@cap-rel/smartcommon'; function MyComponent() { const [session, setSession] = useGlobalStates('session'); const [settings, setSettings] = useGlobalStates('settings'); return (

Utilisateur : {session?.user?.name}

Langue : {settings?.lng}

); } ``` ### Configuration de la persistance Dans `appConfig.js` : ```javascript export const config = { storage: { local: ["session", "settings"] // Persisté en localStorage }, globalState: { reducers: { session: null, settings: { lng: "fr", theme: "light" }, cart: { items: [], total: 0 } } } }; ``` ### Lecture et écriture ```javascript function SettingsPage() { const [settings, setSettings] = useGlobalStates('settings'); const changeLanguage = (lng) => { setSettings({ ...settings, lng }); }; const changeTheme = (theme) => { setSettings({ ...settings, theme }); }; return (
); } ``` ### Exemple : Panier d'achat ```javascript function useCart() { const [cart, setCart] = useGlobalStates('cart'); const addItem = (product) => { const existing = cart.items.find(i => i.id === product.id); let newItems; if (existing) { newItems = cart.items.map(i => i.id === product.id ? { ...i, quantity: i.quantity + 1 } : i ); } else { newItems = [...cart.items, { ...product, quantity: 1 }]; } const total = newItems.reduce( (sum, i) => sum + i.price * i.quantity, 0 ); setCart({ items: newItems, total }); }; const removeItem = (productId) => { const newItems = cart.items.filter(i => i.id !== productId); const total = newItems.reduce( (sum, i) => sum + i.price * i.quantity, 0 ); setCart({ items: newItems, total }); }; const clearCart = () => { setCart({ items: [], total: 0 }); }; return { cart, addItem, removeItem, clearCart }; } // Utilisation function ProductCard({ product }) { const { addItem } = useCart(); return (

{product.label}

{product.price} €

); } function CartIcon() { const { cart } = useCart(); const itemCount = cart.items.reduce((sum, i) => sum + i.quantity, 0); return 🛒 {itemCount}; } ``` ## useStates État local avec notation par chemin (path notation). ### Syntaxe de base ```javascript import { useStates } from '@cap-rel/smartcommon'; function MyComponent() { const st = useStates({ initialStates: { count: 0, user: { name: '', email: '' }, items: [], loading: false }, debug: true // Affiche les changements en console }); return (

Count: {st.get('count')}

); } ``` ### Méthodes disponibles ^ Méthode ^ Description ^ | st.get(path) | Lire une valeur | | st.set(path, value) | Écrire une valeur | | st.unset(path) | Supprimer une valeur | | st.values | Objet contenant toutes les valeurs | ### Path notation ```javascript const st = useStates({ initialStates: { user: { name: '', address: { city: '' } }, items: [] } }); // Lecture st.get('user'); // { name: '', address: { city: '' } } st.get('user.name'); // '' st.get('user.address.city'); // '' st.get('items'); // [] st.get('items[0]'); // undefined // Écriture st.set('user.name', 'Jean'); st.set('user.address.city', 'Paris'); // Écriture avec fonction st.set('count', prev => prev + 1); // Manipulation de tableaux st.set('items[]', { id: 1 }); // Push st.set('items[0].name', 'test'); // Modifier index st.unset('items[0]'); // Supprimer index ``` ### Exemple : Page de détail ```javascript import { useEffect } from 'react'; import { useParams } from 'react-router-dom'; import { Page, Block, Spinner } from '@cap-rel/smartcommon'; import { useApi, useStates } from '@cap-rel/smartcommon'; export const ProductDetailPage = () => { const { id } = useParams(); const api = useApi(); const st = useStates({ initialStates: { product: null, loading: true, error: null, isEditing: false } }); useEffect(() => { loadProduct(); }, [id]); const loadProduct = async () => { st.set('loading', true); st.set('error', null); try { const data = await api.private.get(`products/${id}`).json(); st.set('product', data); } catch (err) { st.set('error', err.message); } finally { st.set('loading', false); } }; if (st.get('loading')) { return ; } if (st.get('error')) { return Erreur : {st.get('error')}; } const product = st.get('product'); return (

Prix : {product.price} €

Stock : {product.stock}

); }; ``` ## useForm Hook spécialisé pour les formulaires avec validation. ### Syntaxe de base ```javascript import { useForm } from '@cap-rel/smartcommon'; import { Form, Input, Button } from '@cap-rel/smartcommon'; import { z } from 'zod'; const schema = z.object({ email: z.string().email('Email invalide'), password: z.string().min(6, 'Minimum 6 caractères') }); function LoginForm() { const form = useForm({ schema }); const handleSubmit = async (data) => { console.log('Données validées:', data); }; return (
); } ``` ### Avec valeurs initiales ```javascript function EditProductForm({ product }) { const form = useForm({ schema: productSchema, defaultValues: { label: product.label, price: product.price, description: product.description } }); const handleSubmit = async (data) => { await api.private.put(`products/${product.id}`, { json: data }); }; return (