Table des matières

Astuces

Cette page regroupe des astuces et bonnes pratiques pour le développement avec SmartMaker.

Utiliser la configuration

SmartCommon utilise LibConfigProvider pour centraliser la configuration de l'application.

// src/appConfig.js

export const appConfig = {
  debug: true, // Active les logs de debug
  api: {
    prefixUrl: import.meta.env.VITE_API_URL,
    timeout: 30000,
    debug: true
  }
};
// src/App.jsx

import { Provider } from '@cap-rel/smartcommon';
import { appConfig } from './appConfig';

export const App = () => {
  return (
    <Provider config={appConfig}>
      {/* Votre application */}
    </Provider>
  );
};

Pour accéder à la configuration dans un composant :

import { useLibConfig } from '@cap-rel/smartcommon';

const MyComponent = () => {
  const config = useLibConfig();
  console.log(config.debug); // true
};

Composant Head

Pour modifier le titre et les meta de la page, utilisez react-helmet :

import { Helmet } from 'react-helmet';

export const MyPage = () => {
  return (
    <>
      <Helmet>
        <title>Ma Page - Mon App</title>
        <meta name="description" content="Description de ma page" />
      </Helmet>
      {/* Contenu de la page */}
    </>
  );
};

Composant Toaster

SmartCommon intègre react-hot-toast pour les notifications.

import toast from 'react-hot-toast';

// Notification de succès
toast.success('Enregistré avec succès !');

// Notification d'erreur
toast.error('Une erreur est survenue');

// Notification personnalisée
toast('Message neutre', {
  icon: '👋',
  duration: 4000,
});

// Notification avec promesse
toast.promise(
  saveData(),
  {
    loading: 'Enregistrement...',
    success: 'Données enregistrées',
    error: 'Échec de l\'enregistrement',
  }
);

Le Toaster est automatiquement inclus dans le Provider de SmartCommon.

Utiliser les variables d'environnement

Dans un environnement Vite, les variables d'environnement doivent être préfixées de VITE_.

# .env

VITE_API_URL=https://api.example.com
VITE_APP_VERSION=1.0.0
VITE_APP_NAME=Mon Application

On peut ainsi les importer avec import.meta.env :

// src/utils/constants/vite.js

export const API_URL     = import.meta.env.VITE_API_URL;
export const APP_VERSION = import.meta.env.VITE_APP_VERSION;
export const APP_NAME    = import.meta.env.VITE_APP_NAME;

<note important>Ne jamais commiter le fichier .env. Utilisez .env.example comme modèle.</note>

Fichiers de traductions publiques

Les fichiers de traduction peuvent être chargés dynamiquement depuis le dossier public :

public/
  locales/
    fr.json
    en.json
    es.json

Configuration i18next :

// src/i18n/index.js

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import HttpBackend from 'i18next-http-backend';

i18n
  .use(HttpBackend)
  .use(initReactI18next)
  .init({
    fallbackLng: 'fr',
    backend: {
      loadPath: '/locales/{{lng}}.json',
    },
  });

export { i18n };

Faire des fichiers de traductions "namespace"

Pour organiser les traductions par fonctionnalité :

public/
  locales/
    fr/
      common.json
      login.json
      dashboard.json
    en/
      common.json
      login.json
      dashboard.json

Configuration :

i18n.init({
  ns: ['common', 'login', 'dashboard'],
  defaultNS: 'common',
  backend: {
    loadPath: '/locales/{{lng}}/{{ns}}.json',
  },
});

Utilisation :

const { t } = useTranslation('login');
// ou
const { t } = useTranslation(['login', 'common']);

Utiliser des préfixes avec useTranslation

Pour éviter de répéter le chemin des clés :

// Sans préfixe
const { t } = useTranslation();
t('loginPage.form.emailInput.label');
t('loginPage.form.emailInput.placeholder');
t('loginPage.form.passwordInput.label');

// Avec préfixe
const { t } = useTranslation('translation', { keyPrefix: 'loginPage.form' });
t('emailInput.label');
t('emailInput.placeholder');
t('passwordInput.label');

Fichiers CSS publiques

Les fichiers CSS dans public/ ne sont pas traités par Vite et sont servis tels quels :

public/
  css/
    custom-theme.css

Pour les charger dynamiquement :

// Charger un thème CSS au runtime
const loadTheme = (themeName) => {
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = `/css/${themeName}.css`;
  document.head.appendChild(link);
};

Retirer Tailwind CSS

Si vous ne souhaitez pas utiliser Tailwind CSS :

  1. Supprimer les dépendances :
npm uninstall tailwindcss @tailwindcss/vite
  1. Modifier vite.config.js :
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// Retirer: import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [
    react(),
    // Retirer: tailwindcss(),
  ]
});
  1. Supprimer les imports Tailwind dans vos fichiers CSS :
/* Retirer: @import "tailwindcss"; */

Importer les fichiers CSS entre eux

Avec Tailwind CSS 4

/* src/assets/styles/style.css */

@import "tailwindcss";

@layer theme, base, components;

@import "./theme.css" layer(theme);
@import "./base.css" layer(base);
@import "./components.css" layer(components);

En CSS classique

/* src/assets/styles/style.css */

@import "./variables.css";
@import "./base.css";
@import "./components.css";

Faire un listener de changement de thème

Pour détecter et réagir aux changements de thème (clair/sombre) :

import { useEffect, useState } from 'react';

export const useThemeDetector = () => {
  const [isDark, setIsDark] = useState(
    window.matchMedia('(prefers-color-scheme: dark)').matches
  );

  useEffect(() => {
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

    const handleChange = (e) => {
      setIsDark(e.matches);
    };

    mediaQuery.addEventListener('change', handleChange);

    return () => mediaQuery.removeEventListener('change', handleChange);
  }, []);

  return isDark;
};

Utilisation :

const MyComponent = () => {
  const isDarkMode = useThemeDetector();

  return (
    <div className={isDarkMode ? 'dark-theme' : 'light-theme'}>
      Mode actuel : {isDarkMode ? 'Sombre' : 'Clair'}
    </div>
  );
};

Pour changer le thème manuellement avec useGlobalStates :

import { useGlobalStates } from '@cap-rel/smartcommon';

const ThemeSwitcher = () => {
  const gst = useGlobalStates();
  const theme = gst.get('settings.theme') || 'light';

  const toggleTheme = () => {
    gst.local.set('settings.theme', theme === 'light' ? 'dark' : 'light');
  };

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
  }, [theme]);

  return (
    <button onClick={toggleTheme}>
      Passer en mode {theme === 'light' ? 'sombre' : 'clair'}
    </button>
  );
};

Voir aussi