Développement d'applications modernes avec React
Guide complet pour créer des applications web performantes et maintenables avec React.
InSkillCoach
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
- Structurez votre projet : Organisez vos fichiers par fonctionnalité ou type
- Utilisez des composants fonctionnels : Plus simples et plus performants avec les Hooks
- Évitez les props drilling : Utilisez Context ou une bibliothèque de gestion d’état
- Écrivez des tests : Assurez-vous que votre application fonctionne comme prévu
- Optimisez les performances : Utilisez React.memo, useMemo et useCallback judicieusement
- Suivez les principes SOLID : Créez des composants à responsabilité unique
- Utilisez TypeScript : Ajoutez du typage statique pour éviter les erreurs
- 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.
À 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+
Commentaires
Les commentaires sont alimentés par GitHub Discussions
Connectez-vous avec GitHub pour participer à la discussion