# Chapitre 3 : Hooks utilitaires SmartCommon fournit des hooks utilitaires pour les tâches courantes. ## useNavigation Navigation programmatique avec React Router. ```javascript import { useNavigation } from '@cap-rel/smartcommon'; function MyComponent() { const navigate = useNavigation(); return (
{/* Navigation vers une route */} {/* Navigation avec paramètre */} {/* Retour arrière */} {/* Remplacement (sans historique) */}
); } ``` ## useLibConfig Accès à la configuration de l'application. ```javascript import { useLibConfig } from '@cap-rel/smartcommon'; function DebugInfo() { const config = useLibConfig(); if (!config.debug) return null; return (

API URL: {config.api.prefixUrl}

Mode: {config.debug ? 'Debug' : 'Production'}

); } ``` ## useIntl Formatage de dates et nombres avec l'API Intl. ### Formatage de dates ```javascript import { useIntl } from '@cap-rel/smartcommon'; function EventCard({ event }) { const intl = useIntl(); // Format par défaut const dateFormatted = intl.DateTimeFormat(event.date); // "15/03/2024, 14:30:00" // Format personnalisé const dateOnly = intl.DateTimeFormat(event.date, 'fr-FR', { year: 'numeric', month: 'long', day: 'numeric' }); // "15 mars 2024" // Heure seule const timeOnly = intl.DateTimeFormat(event.date, 'fr-FR', { hour: '2-digit', minute: '2-digit' }); // "14:30" return (

{event.title}

Le {dateOnly} à {timeOnly}

); } ``` ### Formatage de nombres ```javascript function PriceDisplay({ price, currency = 'EUR' }) { const intl = useIntl(); const formatted = intl.NumberFormat(price, 'fr-FR', { style: 'currency', currency: currency }); // "29,99 €" return {formatted}; } function PercentDisplay({ value }) { const intl = useIntl(); const formatted = intl.NumberFormat(value, 'fr-FR', { style: 'percent', minimumFractionDigits: 1 }); // "15,5 %" return {formatted}; } ``` ## useWindow Informations sur la fenêtre du navigateur. ```javascript import { useWindow } from '@cap-rel/smartcommon'; function ResponsiveLayout({ children }) { const { width, height, isMobile, isTablet, isDesktop } = useWindow(); if (isMobile) { return {children}; } if (isTablet) { return {children}; } return {children}; } function WindowInfo() { const { width, height } = useWindow(); return

Fenêtre : {width} x {height}

; } ``` ## useFile Utilitaires pour la manipulation de fichiers. ### Redimensionner une image ```javascript import { useFile } from '@cap-rel/smartcommon'; function ImageUploader({ onUpload }) { const { resizeImage } = useFile(); const handleFileChange = async (e) => { const file = e.target.files[0]; if (!file) return; // Redimensionner avant upload const base64 = await resizeImage(file, { maxWidth: 1920, maxHeight: 1080, quality: 85 }); // base64 = "data:image/jpeg;base64,..." onUpload(base64); }; return ( ); } ``` ## useDb Base de données IndexedDB via Dexie pour le stockage local de grandes quantités de données. ### Configuration ```javascript import { useDb } from '@cap-rel/smartcommon'; const db = useDb({ name: 'myApp', version: 1, stores: { items: 'id++, name, category, createdAt', logs: 'id++, action, timestamp' }, debug: true }); ``` ### Opérations CRUD ```javascript function ItemsManager() { const db = useDb({ name: 'myApp', version: 1, stores: { items: 'id++, name, category' } }); // Créer const addItem = async (item) => { const id = await db.items.add(item); console.log('Item créé avec id:', id); return id; }; // Lire tous const getAllItems = async () => { return db.items.toArray(); }; // Lire un const getItem = async (id) => { return db.items.get(id); }; // Modifier const updateItem = async (id, changes) => { await db.items.update(id, changes); }; // Supprimer const deleteItem = async (id) => { await db.items.delete(id); }; // ... } ``` ### Requêtes avancées ```javascript // Filtrer par valeur const electronics = await db.items .where('category') .equals('electronics') .toArray(); // Filtrer par plage const expensiveItems = await db.items .where('price') .above(100) .toArray(); // Trier const sorted = await db.items .orderBy('createdAt') .reverse() .toArray(); // Limiter const first10 = await db.items .limit(10) .toArray(); // Compter const count = await db.items.count(); // Recherche texte const matching = await db.items .filter(item => item.name.includes('test')) .toArray(); ``` ### Exemple : Mode offline ```javascript import { useEffect } from 'react'; import { useApi, useDb, useStates } from '@cap-rel/smartcommon'; function OfflineCapableList() { const api = useApi(); const db = useDb({ name: 'myApp', version: 1, stores: { items: 'id, name, synced' } }); const st = useStates({ initialStates: { items: [], loading: true } }); useEffect(() => { loadItems(); }, []); const loadItems = async () => { try { // Essayer de charger depuis l'API const data = await api.private.get('items').json(); // Sauvegarder en local await db.items.clear(); await db.items.bulkAdd(data.map(i => ({ ...i, synced: true }))); st.set('items', data); } catch (err) { // En cas d'erreur réseau, charger depuis IndexedDB console.log('Mode offline - chargement local'); const localItems = await db.items.toArray(); st.set('items', localItems); } finally { st.set('loading', false); } }; const addItem = async (item) => { // Sauvegarder localement d'abord const id = await db.items.add({ ...item, synced: false }); // Mettre à jour l'UI st.set('items', [...st.get('items'), { ...item, id }]); // Tenter de synchroniser try { const result = await api.private.post('items', { json: item }).json(); await db.items.update(id, { ...result, synced: true }); } catch (err) { console.log('Sync échouée, sera retentée plus tard'); } }; // ... } ``` ## useAnimation Gestion d'animations avec Framer Motion. ```javascript import { useAnimation } from '@cap-rel/smartcommon'; import { motion } from 'framer-motion'; function AnimatedList({ items }) { const { start } = useAnimation(); return (
{items.map((item, index) => ( {item.name} ))}
); } ``` ## useListDnD Drag and drop pour réordonner des listes. ```javascript import { useListDnD } from '@cap-rel/smartcommon'; function SortableList({ initialItems, onReorder }) { const { items, handleDragStart, handleDragOver, handleDrop } = useListDnD({ initialItems, onReorder: (newItems) => { console.log('Nouvel ordre:', newItems); onReorder(newItems); } }); return ( ); } ``` ## Tableau récapitulatif ^ Hook ^ Usage ^ Exemple ^ | useNavigation | Navigation | navigate('/products') | | useLibConfig | Config app | config.debug | | useIntl | Formatage | intl.DateTimeFormat(date) | | useWindow | Responsive | isMobile, width | | useFile | Fichiers | resizeImage(file, options) | | useDb | IndexedDB | db.items.add(item) | | useAnimation | Animations | start (boolean) | | useListDnD | Drag & drop | handleDragStart, handleDrop | ## Points clés à retenir 1. **useNavigation** pour la navigation programmatique 2. **useIntl** pour le formatage localisé 3. **useWindow** pour le responsive design 4. **useFile** pour le traitement d'images 5. **useDb** pour le stockage local (offline) [[:15_training:module7-smartcommon-hooks:etat|← Chapitre précédent]] | [[:15_training:module7-smartcommon-hooks:start|Retour au module]] | [[:15_training:module8-backend-api:start|Module suivant : Backend API →]]