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() → gst.get('session')
Préférences useGlobalStates() → gst.get('settings')
Données partagées useGlobalStates() → gst.get/set
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 manuelle avec setField

snippet.javascript
// useForm ne fait pas de validation automatique.
// Validez les champs manuellement :
form.setField({
    name: 'email',
    value: inputValue,
    errors: {
        required: { condition: !inputValue },
        format: { condition: inputValue && !inputValue.includes('@') }
    }
});

Affichage des erreurs

snippet.javascript
// Vérifier les erreurs
const hasError = form.get('errors.email.required');
const hasFormatError = form.get('errors.email.format');

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 manuelle avec setField
      • Affichage des erreurs
    • 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
    • Synchronisation offline
    • 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 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
      • Chapitre 4 : Synchronisation Offline
    • 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