SmarMaker - Documentation
Docs» 15_training:module7-smartcommon-hooks:utilitaires

Chapitre 3 : Hooks utilitaires

SmartCommon fournit des hooks utilitaires pour les tâches courantes.

useNavigation

Navigation programmatique avec React Router.

snippet.javascript
import { useNavigation } from '@cap-rel/smartcommon';
 
function MyComponent() {
    const navigate = useNavigation();
 
    return (
        <div>
            {/* Navigation vers une route */}
            <button onClick={() => navigate('/products')}>
                Produits
            </button>
 
            {/* Navigation avec paramètre */}
            <button onClick={() => navigate(`/products/${id}`)}>
                Détails
            </button>
 
            {/* Retour arrière */}
            <button onClick={() => navigate(-1)}>
                Retour
            </button>
 
            {/* Remplacement (sans historique) */}
            <button onClick={() => navigate('/login', { replace: true })}>
                Login
            </button>
        </div>
    );
}

useLibConfig

Accès à la configuration de l'application.

snippet.javascript
import { useLibConfig } from '@cap-rel/smartcommon';
 
function DebugInfo() {
    const config = useLibConfig();
 
    if (!config.debug) return null;
 
    return (
        <div className="debug-panel">
            <p>API URL: {config.api.prefixUrl}</p>
            <p>Mode: {config.debug ? 'Debug' : 'Production'}</p>
        </div>
    );
}

useIntl

Formatage de dates et nombres avec l'API Intl.

Formatage de dates

snippet.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 (
        <div>
            <h3>{event.title}</h3>
            <p>Le {dateOnly} à {timeOnly}</p>
        </div>
    );
}

Formatage de nombres

snippet.javascript
function PriceDisplay({ price, currency = 'EUR' }) {
    const intl = useIntl();
 
    const formatted = intl.NumberFormat(price, 'fr-FR', {
        style: 'currency',
        currency: currency
    });
    // "29,99 €"
 
    return <span>{formatted}</span>;
}
 
function PercentDisplay({ value }) {
    const intl = useIntl();
 
    const formatted = intl.NumberFormat(value, 'fr-FR', {
        style: 'percent',
        minimumFractionDigits: 1
    });
    // "15,5 %"
 
    return <span>{formatted}</span>;
}

useWindow

Informations sur la fenêtre du navigateur.

snippet.javascript
import { useWindow } from '@cap-rel/smartcommon';
 
function ResponsiveLayout({ children }) {
    const { width, height, isMobile, isTablet, isDesktop } = useWindow();
 
    if (isMobile) {
        return <MobileLayout>{children}</MobileLayout>;
    }
 
    if (isTablet) {
        return <TabletLayout>{children}</TabletLayout>;
    }
 
    return <DesktopLayout>{children}</DesktopLayout>;
}
 
function WindowInfo() {
    const { width, height } = useWindow();
 
    return <p>Fenêtre : {width} x {height}</p>;
}

useFile

Utilitaires pour la manipulation de fichiers.

Redimensionner une image

snippet.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 (
        <input
            type="file"
            accept="image/*"
            onChange={handleFileChange}
        />
    );
}

useDb

Base de données IndexedDB via Dexie pour le stockage local de grandes quantités de données.

Configuration

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

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

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

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

snippet.javascript
import { useAnimation } from '@cap-rel/smartcommon';
import { motion } from 'framer-motion';
 
function AnimatedList({ items }) {
    const { start } = useAnimation();
 
    return (
        <div>
            {items.map((item, index) => (
                <motion.div
                    key={item.id}
                    initial={{ opacity: 0, y: 20 }}
                    animate={start ? { opacity: 1, y: 0 } : {}}
                    transition={{ delay: index * 0.1 }}
                >
                    {item.name}
                </motion.div>
            ))}
        </div>
    );
}

useListDnD

Drag and drop pour réordonner des listes.

snippet.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 (
        <ul>
            {items.map((item, index) => (
                <li
                    key={item.id}
                    draggable
                    onDragStart={(e) => handleDragStart(e, index)}
                    onDragOver={handleDragOver}
                    onDrop={(e) => handleDrop(e, index)}
                >
                    {item.name}
                </li>
            ))}
        </ul>
    );
}

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)

← Chapitre précédent | Retour au module | Module suivant : Backend API →

Previous Next

Made with ❤ by CAP-REL · SmartMaker · GNU AGPL v3+
Code source · Faire un don
SmarMaker - Documentation
Traductions de cette page:
  • Français
  • Deutsch
  • English
  • Español
  • Italiano
  • Nederlands

Table of Contents

Table des matières

  • Chapitre 3 : Hooks utilitaires
    • useNavigation
    • useLibConfig
    • useIntl
      • Formatage de dates
      • Formatage de nombres
    • useWindow
    • useFile
      • Redimensionner une image
    • useDb
      • Configuration
      • Opérations CRUD
      • Requêtes avancées
      • Exemple : Mode offline
    • useAnimation
    • useListDnD
    • Tableau récapitulatif
    • Points clés à retenir
  • SmartAuth
  • SmartMaker - Back (PHP)
    • Mapping Dolibarr - React
  • SmartMaker - Front (React)
    • Animations de pages
    • Architecture
    • Astuces
    • Calendar
    • Composants et pages
    • Configuration du Provider
    • Debug et Logs
    • Hooks SmartCommon
    • PWA (Progressive Web App)
    • Requêtes API
    • Routage
    • SmartCommon
    • Stockage de données
    • Thèmes
    • Traductions
  • HowTo - Pas à pas - Votre première application
    • Développement PHP (back)
    • Développement React (front)
    • Première étape : Module Builder Dolibarr
    • SmartAuth
    • SmartBoot : Un "squelette" quasiment prêt à l'emploi
  • Formation SmartMaker
    • Module 1 : Fondamentaux JavaScript ES6+
      • Chapitre 1 : Variables et Scope
      • Chapitre 2 : Fonctions
      • Chapitre 3 : Programmation Asynchrone
      • Chapitre 4 : Modules ES6
    • Module 2 : Introduction à React
      • Chapitre 1 : Philosophie React
      • Chapitre 2 : JSX
      • Chapitre 3 : Composants
    • Module 3 : Hooks React Fondamentaux
      • Chapitre 1 : useState
      • Chapitre 2 : useEffect
      • Chapitre 3 : useRef
      • Chapitre 4 : useContext
    • Module 4 : React Avancé
      • Chapitre 1 : useCallback et useMemo
      • Chapitre 2 : Custom Hooks
      • Chapitre 3 : Redux et Redux Toolkit
    • Module 5 : Architecture SmartMaker
      • Chapitre 1 : Structure du projet
      • Chapitre 2 : Configuration
      • Chapitre 3 : Flux de données
    • Module 6 : SmartCommon - Composants
      • Chapitre 1 : Mise en page
      • Chapitre 2 : Navigation
      • Chapitre 3 : Formulaires
      • Chapitre 4 : Affichage
    • Module 7 : SmartCommon - Hooks
      • Chapitre 1 : useApi
      • Chapitre 2 : Gestion d'état
      • Chapitre 3 : Hooks utilitaires
    • Module 8 : Backend API (PHP)
      • Chapitre 1 : Routage
      • Chapitre 2 : Controllers
      • Chapitre 3 : Mappers
      • Extrafields et formulaires dynamiques
    • Module 9 : Intégration complète
      • Chapitre 1 : Backend
      • Chapitre 2 : Frontend
      • Chapitre 3 : Déploiement
    • Module 10 : Fonctionnalités avancées
      • Chapitre 1 : Mode offline
      • Chapitre 2 : Internationalisation (i18n)
      • Chapitre 3 : Autres fonctionnalités
    • Module 11 : Bonnes pratiques
  • Démonstration
  • Start
  • Composants et pages
  • Afficher le texte source
  • Anciennes révisions
  • Liens de retour
  • Haut de page