0%
Développement d'applications modernes avec React

Développement d'applications modernes avec React

Guide complet pour créer des applications web performantes et maintenables avec React.

I

InSkillCoach

· min

Développement d’applications modernes avec React

React est l’une des bibliothèques JavaScript les plus populaires pour la création d’interfaces utilisateur. Développée et maintenue par Facebook (Meta), elle permet de construire des applications web complexes avec des composants réutilisables et une gestion efficace de l’état.

Pourquoi choisir React ?

  • Approche déclarative : Vous décrivez à quoi devrait ressembler votre UI, React s’occupe des mises à jour
  • Basé sur les composants : Créez des éléments d’interface encapsulés et réutilisables
  • Écosystème riche : Un large éventail de bibliothèques et d’outils complémentaires
  • Grande communauté : Support, ressources et mises à jour régulières
  • Performances optimisées : Virtual DOM et réconciliation pour des mises à jour efficaces
  • Adopté par les grandes entreprises : Facebook, Instagram, Netflix, Airbnb, etc.

Mise en place d’un projet React

Création avec Create React App

Create React App est un outil officiel qui permet de démarrer rapidement un projet React :

# Installation
npx create-react-app mon-application

# Démarrage
cd mon-application
npm start

Utilisation de Vite (alternative moderne)

Vite offre des temps de compilation plus rapides et une meilleure expérience de développement :

# Installation
npm create vite@latest mon-application -- --template react

# Démarrage
cd mon-application
npm install
npm run dev

Les fondamentaux de React

Composants

Les composants sont les briques de base d’une application React :

// Composant fonctionnel
function Salutation(props) {
  return <h1>Bonjour, {props.nom} !</h1>;
}

// Utilisation
<Salutation nom="Alice" />

JSX

JSX est une extension de syntaxe qui permet d’écrire du HTML dans du JavaScript :

const element = <h1>Bonjour, monde !</h1>;

// Avec expressions JavaScript
const nom = "Alice";
const element = <h1>Bonjour, {nom} !</h1>;

// Avec attributs
const element = <img src={user.avatarUrl} alt="Avatar" />;

// Éléments imbriqués
const element = (
  <div>
    <h1>Titre</h1>
    <p>Paragraphe</p>
  </div>
);

Props

Les props permettent de passer des données d’un composant parent à un composant enfant :

// Définition du composant
function Carte(props) {
  return (
    <div className="carte">
      <h2>{props.titre}</h2>
      <p>{props.description}</p>
      {props.children}
    </div>
  );
}

// Utilisation
<Carte 
  titre="Mon titre" 
  description="Ma description"
>
  <button>En savoir plus</button>
</Carte>

État (State)

L’état permet de stocker des données qui peuvent changer au fil du temps :

import { useState } from 'react';

function Compteur() {
  // Déclaration d'un état
  const [compteur, setCompteur] = useState(0);
  
  return (
    <div>
      <p>Vous avez cliqué {compteur} fois</p>
      <button onClick={() => setCompteur(compteur + 1)}>
        Cliquez ici
      </button>
    </div>
  );
}

Cycle de vie avec les Hooks

Les Hooks permettent d’utiliser l’état et d’autres fonctionnalités de React dans les composants fonctionnels :

import { useState, useEffect } from 'react';

function ExempleEffet() {
  const [compteur, setCompteur] = useState(0);
  
  // Similaire à componentDidMount et componentDidUpdate
  useEffect(() => {
    // Met à jour le titre du document
    document.title = `Vous avez cliqué ${compteur} fois`;
    
    // Fonction de nettoyage (similaire à componentWillUnmount)
    return () => {
      document.title = 'React App';
    };
  }, [compteur]); // S'exécute uniquement si compteur change
  
  return (
    <div>
      <p>Vous avez cliqué {compteur} fois</p>
      <button onClick={() => setCompteur(compteur + 1)}>
        Cliquez ici
      </button>
    </div>
  );
}

Gestion des événements

React utilise une syntaxe similaire au HTML pour gérer les événements :

function Bouton() {
  function handleClick(e) {
    e.preventDefault();
    console.log('Le bouton a été cliqué');
  }
  
  return (
    <button onClick={handleClick}>
      Cliquez ici
    </button>
  );
}

Rendu conditionnel

Vous pouvez afficher différents éléments en fonction de conditions :

function Connexion(props) {
  const estConnecte = props.estConnecte;
  
  return (
    <div>
      {estConnecte ? (
        <BoutonDeconnexion />
      ) : (
        <BoutonConnexion />
      )}
    </div>
  );
}

// Autre approche
function Message(props) {
  const nonLu = props.messagesNonLus.length;
  
  return (
    <div>
      <h1>Bonjour !</h1>
      {nonLu > 0 && (
        <p>Vous avez {nonLu} message(s) non lu(s).</p>
      )}
    </div>
  );
}

Listes et clés

Pour afficher des listes d’éléments, utilisez map() et des clés uniques :

function ListeArticles(props) {
  const articles = props.articles;
  
  return (
    <ul>
      {articles.map((article) => (
        <li key={article.id}>
          {article.titre}
        </li>
      ))}
    </ul>
  );
}

Gestion avancée de l’état

Context API

Le Context API permet de partager des données entre des composants sans passer par les props :

// Création du contexte
const ThemeContext = React.createContext('light');

// Fournisseur de contexte
function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

// Consommation du contexte avec useContext
function Bouton() {
  const theme = useContext(ThemeContext);
  
  return (
    <button className={theme}>
      Je suis stylisé selon le thème {theme}
    </button>
  );
}

useReducer pour une gestion d’état complexe

useReducer est préférable à useState pour des états complexes :

import { useReducer } from 'react';

// Définition du reducer
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { compteur: state.compteur + 1 };
    case 'decrement':
      return { compteur: state.compteur - 1 };
    default:
      throw new Error();
  }
}

function Compteur() {
  // Utilisation du reducer
  const [state, dispatch] = useReducer(reducer, { compteur: 0 });
  
  return (
    <div>
      Compteur: {state.compteur}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

Bibliothèques de gestion d’état

Pour des applications plus complexes, vous pouvez utiliser des bibliothèques dédiées :

Redux

// Actions
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';

// Action creators
function increment() {
  return { type: INCREMENT };
}

// Reducer
function compteurReducer(state = { valeur: 0 }, action) {
  switch (action.type) {
    case INCREMENT:
      return { valeur: state.valeur + 1 };
    case DECREMENT:
      return { valeur: state.valeur - 1 };
    default:
      return state;
  }
}

// Store
const store = createStore(compteurReducer);

// Composant connecté
function Compteur({ valeur, increment, decrement }) {
  return (
    <div>
      <span>{valeur}</span>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
}

const mapStateToProps = state => ({
  valeur: state.valeur
});

const mapDispatchToProps = {
  increment,
  decrement
};

export default connect(mapStateToProps, mapDispatchToProps)(Compteur);

Zustand (alternative moderne)

import create from 'zustand';

// Création du store
const useStore = create(set => ({
  compteur: 0,
  increment: () => set(state => ({ compteur: state.compteur + 1 })),
  decrement: () => set(state => ({ compteur: state.compteur - 1 })),
}));

// Utilisation dans un composant
function Compteur() {
  const { compteur, increment, decrement } = useStore();
  
  return (
    <div>
      <span>{compteur}</span>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
}

Routage avec React Router

React Router permet de gérer la navigation dans une application React :

import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Accueil</Link>
        <Link to="/a-propos">À propos</Link>
        <Link to="/contact">Contact</Link>
      </nav>
      
      <Routes>
        <Route path="/" element={<Accueil />} />
        <Route path="/a-propos" element={<APropos />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="/produits/:id" element={<DetailProduit />} />
        <Route path="*" element={<PageNonTrouvee />} />
      </Routes>
    </BrowserRouter>
  );
}

// Accès aux paramètres d'URL
import { useParams } from 'react-router-dom';

function DetailProduit() {
  const { id } = useParams();
  
  return <h1>Détail du produit {id}</h1>;
}

Formulaires en React

Formulaires contrôlés

Dans un formulaire contrôlé, React gère l’état du formulaire :

import { useState } from 'react';

function FormulaireConnexion() {
  const [email, setEmail] = useState('');
  const [motDePasse, setMotDePasse] = useState('');
  
  function handleSubmit(e) {
    e.preventDefault();
    console.log('Email:', email);
    console.log('Mot de passe:', motDePasse);
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>
          Email:
          <input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            required
          />
        </label>
      </div>
      <div>
        <label>
          Mot de passe:
          <input
            type="password"
            value={motDePasse}
            onChange={(e) => setMotDePasse(e.target.value)}
            required
          />
        </label>
      </div>
      <button type="submit">Se connecter</button>
    </form>
  );
}

Bibliothèques de formulaires

Pour des formulaires complexes, utilisez des bibliothèques comme Formik ou React Hook Form :

// Avec React Hook Form
import { useForm } from 'react-hook-form';

function FormulaireInscription() {
  const { register, handleSubmit, formState: { errors } } = useForm();
  
  const onSubmit = data => console.log(data);
  
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label>Nom</label>
        <input {...register('nom', { required: 'Le nom est requis' })} />
        {errors.nom && <p>{errors.nom.message}</p>}
      </div>
      
      <div>
        <label>Email</label>
        <input 
          {...register('email', { 
            required: 'L\'email est requis',
            pattern: {
              value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
              message: 'Adresse email invalide'
            }
          })} 
        />
        {errors.email && <p>{errors.email.message}</p>}
      </div>
      
      <button type="submit">S'inscrire</button>
    </form>
  );
}

Optimisation des performances

React.memo

React.memo permet d’éviter les rendus inutiles des composants fonctionnels :

const MonComposant = React.memo(function MonComposant(props) {
  // Votre composant
});

useMemo et useCallback

Ces hooks permettent de mémoriser des valeurs et des fonctions :

import { useMemo, useCallback } from 'react';

function ExempleOptimisation({ a, b }) {
  // Mémorise le résultat du calcul
  const resultat = useMemo(() => {
    console.log('Calcul coûteux...');
    return a * b;
  }, [a, b]); // Recalcule uniquement si a ou b change
  
  // Mémorise la fonction
  const handleClick = useCallback(() => {
    console.log('Bouton cliqué avec résultat:', resultat);
  }, [resultat]); // Recrée uniquement si resultat change
  
  return (
    <div>
      <p>Résultat: {resultat}</p>
      <button onClick={handleClick}>Cliquer</button>
    </div>
  );
}

Lazy Loading

Le chargement paresseux permet de diviser votre application en morceaux plus petits :

import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

// Chargement paresseux des composants
const Accueil = lazy(() => import('./pages/Accueil'));
const APropos = lazy(() => import('./pages/APropos'));
const Contact = lazy(() => import('./pages/Contact'));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Chargement...</div>}>
        <Routes>
          <Route path="/" element={<Accueil />} />
          <Route path="/a-propos" element={<APropos />} />
          <Route path="/contact" element={<Contact />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

Tests en React

Tests unitaires avec Jest et React Testing Library

// Composant à tester
function Salutation({ nom }) {
  return <h1>Bonjour, {nom} !</h1>;
}

// Test
import { render, screen } from '@testing-library/react';
import Salutation from './Salutation';

test('affiche le message de salutation', () => {
  render(<Salutation nom="Alice" />);
  const element = screen.getByText(/bonjour, alice !/i);
  expect(element).toBeInTheDocument();
});

Tests d’interaction

import { render, screen, fireEvent } from '@testing-library/react';
import Compteur from './Compteur';

test('incrémente le compteur lorsque le bouton est cliqué', () => {
  render(<Compteur />);
  
  // Vérifier la valeur initiale
  expect(screen.getByText(/compteur: 0/i)).toBeInTheDocument();
  
  // Cliquer sur le bouton
  fireEvent.click(screen.getByText('+'));
  
  // Vérifier la nouvelle valeur
  expect(screen.getByText(/compteur: 1/i)).toBeInTheDocument();
});

Déploiement d’une application React

Build de production

# Avec Create React App
npm run build

# Avec Vite
npm run build

Hébergement statique

Vous pouvez déployer votre application sur des plateformes comme :

  • Netlify : Glissez-déposez le dossier build ou configurez un déploiement continu
  • Vercel : Optimisé pour les applications React, déploiement automatique depuis GitHub
  • GitHub Pages : Idéal pour les projets personnels ou open source
  • Firebase Hosting : Solution complète avec authentification et base de données

Bonnes pratiques

  1. Structurez votre projet : Organisez vos fichiers par fonctionnalité ou type
  2. Utilisez des composants fonctionnels : Plus simples et plus performants avec les Hooks
  3. Évitez les props drilling : Utilisez Context ou une bibliothèque de gestion d’état
  4. Écrivez des tests : Assurez-vous que votre application fonctionne comme prévu
  5. Optimisez les performances : Utilisez React.memo, useMemo et useCallback judicieusement
  6. Suivez les principes SOLID : Créez des composants à responsabilité unique
  7. Utilisez TypeScript : Ajoutez du typage statique pour éviter les erreurs
  8. Documentez vos composants : Utilisez des outils comme Storybook

Conclusion

React est une bibliothèque puissante qui permet de créer des interfaces utilisateur modernes et performantes. Sa flexibilité et son écosystème riche en font un excellent choix pour le développement d’applications web de toutes tailles.

En maîtrisant les concepts fondamentaux et les bonnes pratiques présentés dans cet article, vous serez en mesure de créer des applications React robustes, maintenables et évolutives.

InSkillCoach

À propos de InSkillCoach

Expert en formation et technologies

Coach spécialisé dans les technologies avancées et l'IA, porté par GNeurone Inc.

Certifications:

  • AWS Certified Solutions Architect – Professional
  • Certifications Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
1.2k
287

Commentaires

Les commentaires sont alimentés par GitHub Discussions

Connectez-vous avec GitHub pour participer à la discussion

Lien copié !