SmarMaker - Documentation
Docs» 15_training:module11-bonnes-pratiques:start

Module 11 : Bonnes pratiques

Ce module final résume les bonnes pratiques pour le développement d'applications SmartMaker.

Organisation du code

Structure des composants

components/pages/private/TasksPage/
├── index.jsx           # Composant principal (export)
├── TasksPage.jsx       # Logique et rendu
├── components/         # Sous-composants locaux
│   ├── TaskList.jsx
│   └── TaskFilters.jsx
└── hooks/              # Hooks spécifiques à cette page
    └── useTasks.js

Convention de nommage

  • Composants : PascalCase (TaskList, UserProfile)
  • Hooks : camelCase avec préfixe use (useTasks, useAuth)
  • Fichiers : même nom que le composant (TaskList.jsx)
  • Dossiers : PascalCase pour composants, camelCase pour hooks

Performance

Éviter les re-rendus inutiles

snippet.javascript
// Éviter : objet recréé à chaque rendu
<Component style={{ color: 'red' }} />
 
// Préférer : objet stable
const style = useMemo(() => ({ color: 'red' }), []);
<Component style={style} />

Mémoriser les callbacks

snippet.javascript
// Pour les composants mémorisés
const handleClick = useCallback((id) => {
    setSelected(id);
}, []);

Lazy loading des pages

snippet.javascript
import { lazy, Suspense } from 'react';
import { Spinner } from '@cap-rel/smartcommon';
 
const TasksPage = lazy(() => import('./pages/private/TasksPage'));
 
<Suspense fallback={<Spinner />}>
    <TasksPage />
</Suspense>

Gestion d'état

Choisir le bon outil

Besoin Solution
État d'un formulaire useStates ou useForm
État d'une page (loading, error) useStates
Session utilisateur useGlobalStates('session')
Préférences useGlobalStates('settings')
Données partagées useGlobalStates
Gros volumes, offline useDb

Structurer l'état global

snippet.javascript
globalState: {
    reducers: {
        // Auth
        session: null,
 
        // Préférences
        settings: { lng: 'fr', theme: 'light' },
 
        // Cache de données
        cache: {
            categories: [],
            lastFetch: null
        }
    }
}

Appels API

Toujours gérer les erreurs

snippet.javascript
const loadData = async () => {
    st.set('loading', true);
    st.set('error', null);
 
    try {
        const data = await api.private.get('items').json();
        st.set('items', data.items);
    } catch (err) {
        st.set('error', err.message);
        // Log pour debug
        console.error('Load error:', err);
    } finally {
        st.set('loading', false);
    }
};

Annuler les requêtes au démontage

snippet.javascript
useEffect(() => {
    const controller = new AbortController();
 
    const load = async () => {
        try {
            const data = await api.private.get('items', {
                signal: controller.signal
            }).json();
            setItems(data);
        } catch (err) {
            if (err.name !== 'AbortError') {
                setError(err.message);
            }
        }
    };
 
    load();
 
    return () => controller.abort();
}, []);

Formulaires

Validation avec Zod

snippet.javascript
import { z } from 'zod';
 
const schema = z.object({
    email: z.string().email('Email invalide'),
    password: z.string().min(8, 'Minimum 8 caractères'),
    age: z.number().min(18, 'Doit être majeur').optional()
});

Messages d'erreur clairs

snippet.javascript
<Input
    name="email"
    label="Email"
    error={errors.email?.message}
    required
/>

Sécurité

Ne jamais stocker de secrets côté client

snippet.javascript
// JAMAIS
const API_KEY = 'secret123';
 
// OK : variables d'environnement serveur uniquement
// Le client n'a accès qu'aux VITE_ prefixés
const API_URL = import.meta.env.VITE_API_URL;

Valider côté serveur

Ne pas faire confiance aux données du client :

snippet.php
// Controller PHP
public function create($payload)
{
    // Toujours valider
    if (empty($payload['label'])) {
        return ['Label required', 400];
    }
 
    // Toujours vérifier les droits
    if (!$user->hasRight('mymodule', 'create')) {
        return ['Forbidden', 403];
    }
 
    // Toujours échapper
    $label = $db->escape($payload['label']);
}

Protéger contre XSS

React échappe automatiquement, mais attention à dangerouslySetInnerHTML :

snippet.javascript
// Dangereux
<div dangerouslySetInnerHTML={{ __html: userContent }} />
 
// Si nécessaire, sanitiser d'abord
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userContent) }} />

Tests

Tester les composants critiques

snippet.javascript
// TasksPage.test.jsx
import { render, screen, waitFor } from '@testing-library/react';
import { TasksPage } from './TasksPage';
 
test('affiche la liste des tâches', async () => {
    render(<TasksPage />);
 
    await waitFor(() => {
        expect(screen.getByText('Mes tâches')).toBeInTheDocument();
    });
});

Debug

Utiliser les outils

  • React DevTools : inspecter les composants et l'état
  • Redux DevTools : voir les actions et l'état global
  • Console : st.set avec debug: true
snippet.javascript
const st = useStates({
    initialStates: { ... },
    debug: import.meta.env.DEV  // Logs uniquement en dev
});

Checklist avant déploiement

  • [ ] Toutes les erreurs sont gérées
  • [ ] Les chargements affichent un spinner
  • [ ] La validation fonctionne côté client ET serveur
  • [ ] Les droits sont vérifiés côté serveur
  • [ ] Le mode offline fonctionne (si applicable)
  • [ ] Les traductions sont complètes
  • [ ] Les performances sont acceptables
  • [ ] HTTPS est activé
  • [ ] Les variables d'environnement de prod sont configurées

Ressources

  • Documentation React : https://react.dev
  • Documentation SmartCommon : https://inligit.fr/cap-rel/dolibarr/smartmaker/smartcommon
  • Documentation Dolibarr : https://wiki.dolibarr.org

← Chapitre précédent | Retour à l'index de la formation

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

  • Module 11 : Bonnes pratiques
    • Organisation du code
      • Structure des composants
      • Convention de nommage
    • Performance
      • Éviter les re-rendus inutiles
      • Mémoriser les callbacks
      • Lazy loading des pages
    • Gestion d'état
      • Choisir le bon outil
      • Structurer l'état global
    • Appels API
      • Toujours gérer les erreurs
      • Annuler les requêtes au démontage
    • Formulaires
      • Validation avec Zod
      • Messages d'erreur clairs
    • Sécurité
      • Ne jamais stocker de secrets côté client
      • Valider côté serveur
      • Protéger contre XSS
    • Tests
      • Tester les composants critiques
    • Debug
      • Utiliser les outils
    • Checklist avant déploiement
    • Ressources
  • 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