logo oujood
🔍

React Components : Créez des Interfaces Réutilisables

OUJOOD.COM

Introduction

Les composants sont le cœur de React. Ils permettent de découper une interface utilisateur en parties indépendantes et réutilisables. Dans ce chapitre, nous allons explorer :

  • Qu'est-ce qu'un composant React ?
  • Comment créer des composants fonctionnels et basés sur des classes.
  • Des exemples pratiques pour illustrer leur utilisation.

Qu'est-ce qu'un Composant React ?

Un composant React est une fonction ou une classe qui prend des entrées (appelées props) et retourne un élément React décrivant ce qui doit être affiché à l'écran. Les composants peuvent être imbriqués pour créer des interfaces complexes.

Il existe deux types principaux de composants :

  • Composants fonctionnels : Plus simples et modernes, ils utilisent des fonctions JavaScript pour définir l'interface utilisateur.
  • Composants basés sur des classes : Utilisés avant l'introduction des hooks, ils permettent de gérer l'état et le cycle de vie des composants.

1. Composants Fonctionnels

Les composants fonctionnels sont le moyen le plus simple et moderne de créer des composants React. Ils sont basés sur des fonctions JavaScript pures et utilisent une syntaxe concise pour définir l'interface utilisateur.

Qu'est-ce qu'un Composant Fonctionnel ?

Un composant fonctionnel est simplement une fonction JavaScript qui retourne du JSX. Il prend des données (appelées props) comme entrée et génère un élément React à afficher à l'écran.

Voici un exemple simple pour illustrer ce concept :

📋 Copier le code

function Bonjour({ nom }) {
return <h1>Bonjour, {nom} !</h1>;
}

ReactDOM.render(<Bonjour nom="Alice" />, document.getElementById('root'));

Explication ligne par ligne :

  1. function Bonjour({ nom }) { ... } :
    • Ceci définit une fonction JavaScript appelée Bonjour.
    • Les accolades { nom } représentent la destructuration. Cela signifie que nous extrayons automatiquement la propriété nom des props passées au composant.
  2. return <h1>Bonjour, {nom} !</h1>; :
    • Cette ligne retourne du JSX, qui est ensuite interprété par React pour afficher un élément <h1> contenant le texte "Bonjour, Alice !" si nom vaut "Alice".
    • {nom} insère dynamiquement la valeur de la variable nom dans le JSX.
  3. ReactDOM.render(<Bonjour nom="Alice" />, document.getElementById('root')); :
    • Cette ligne utilise ReactDOM.render() pour insérer le composant Bonjour dans le DOM.
    • <Bonjour nom="Alice" /> : Ici, nous utilisons le composant Bonjour en lui passant une prop appelée nom avec la valeur "Alice".
    • document.getElementById('root') : Cette partie indique où dans le DOM le composant doit être rendu. Typiquement, un élément HTML avec l'id root est utilisé comme point d'insertion.

Pourquoi Utiliser des Composants Fonctionnels ?

Les composants fonctionnels sont privilégiés dans React car ils sont simples, faciles à lire et performants. Voici quelques avantages clés :

  • Syntaxe concise : Ils utilisent une syntaxe minimaliste qui facilite leur compréhension.
  • Support des Hooks : Avec l'introduction des hooks (comme useState ou useEffect), les composants fonctionnels peuvent désormais gérer l'état et le cycle de vie sans avoir besoin de classes.
  • Rapidité de développement : Ils permettent d'écrire moins de code tout en restant puissants.

Exemple Étendu : Création d'un Composant Fonctionnel Réutilisable

Imaginons que vous souhaitiez créer un composant qui salue une personne en affichant son prénom et sa ville. Voici comment cela peut être fait :

📋 Copier le code

function Saluer({ nom, ville }) {
return (
<div>
<h1>Bonjour, {nom} !</h1>
<p>Vous habitez à {ville}.</p>
</div>
);
}

// Utilisation du composant
ReactDOM.render(
<Saluer nom="Alice" ville="Paris" />,
document.getElementById('root')
);

Explication détaillée :

  1. function Saluer({ nom, ville }) { ... } :
    • Nous créons une fonction appelée Saluer.
    • Avec { nom, ville }, nous utilisons la destructuration pour extraire directement les propriétés nom et ville des props passées au composant.
  2. return ( ... ); :
    • La fonction retourne une structure JSX contenant deux éléments : un <h1> et un <p>.
    • {nom} et {ville} insèrent dynamiquement les valeurs des props correspondantes dans le JSX.
  3. ReactDOM.render( ... ) :
    • Cette méthode rend le composant Saluer dans l'élément HTML ayant l'id root.
    • <Saluer nom="Alice" ville="Paris" /> : Nous passons deux props (nom et ville) avec leurs valeurs respectives.

Comment Passer des Props à un Composant Fonctionnel ?

Les props sont des données transmises d'un composant parent à un composant enfant. Elles permettent de rendre le composant réutilisable en acceptant différentes valeurs selon l'utilisation.

Voici un exemple où le même composant est utilisé plusieurs fois avec des props différentes :

📋 Copier le code

function Saluer({ nom, ville }) {
return (
<div>
<h1>Bonjour, {nom} !</h1>
<p>Vous habitez à {ville}.</p>
</div>
);
}

function App() {
return (
<div>
<Saluer nom="Alice" ville="Paris" />
<Saluer nom="Bob" ville="Lyon" />
<Saluer nom="Charlie" ville="Marseille" />
</div>
);
}

ReactDOM.render(<App />, document.getElementById('root'));

Explication détaillée :

  1. function App() { ... } :
    • Nous créons un composant parent appelé App.
    • Ce composant utilise trois instances du composant Saluer, chacune avec des props différentes.
  2. <Saluer nom="Alice" ville="Paris" /> :
    • Ici, nous utilisons le composant Saluer avec les props nom="Alice" et ville="Paris".
    • Cela affichera :
      			<h1>Bonjour, Alice !</h1>
      			<p>Vous habitez à Paris.</p>
      		
  3. ReactDOM.render(<App />, document.getElementById('root')); :
    • Cette ligne rend le composant App dans l'élément HTML ayant l'id root.
    • Le composant App inclut trois instances du composant Saluer, chacune avec ses propres props.

Composants Fonctionnels avec État (Hooks)

Bien que les composants fonctionnels soient initialement statiques, ils peuvent désormais gérer l'état grâce aux hooks (introduits dans React 16.8). Le hook useState est particulièrement utile pour ajouter un état local à un composant fonctionnel.

Voici un exemple de compteur utilisant useState :

📋 Copier le code

import React, { useState } from 'react';

function Compteur() {
// Initialisation de l'état "compte" avec la valeur 0
const [compte, setCompte] = useState(0);

// Fonction pour incrémenter le compteur
function incrementer() {
setCompte(compte + 1);
}

return (
<div>
<p>Vous avez cliqué {compte} fois.</p>
<button onClick={incrementer}>
	Cliquez ici
</button>
</div>
);
}

ReactDOM.render(<Compteur />, document.getElementById('root'));

Explication détaillée :

  1. import React, { useState } from 'react'; :
    • Nous importons React et le hook useState depuis la bibliothèque React.
  2. const [compte, setCompte] = useState(0); :
    • useState est un hook qui permet d'ajouter un état local à un composant fonctionnel.
    • compte représente la valeur actuelle de l'état.
    • setCompte est une fonction qui met à jour cette valeur.
    • Ici, nous initialisons compte à 0.
  3. function incrementer() { setCompte(compte + 1); } :
    • Cette fonction incrémente la valeur de compte lorsque le bouton est cliqué.
    • setCompte(compte + 1) met à jour l'état en ajoutant 1 à la valeur actuelle de compte.
  4. onClick={incrementer} :
    • Cet attribut lie la fonction incrementer à l'événement de clic du bouton.
    • Lorsque le bouton est cliqué, incrementer est exécutée, mettant à jour l'état.

Conclusion

Les composants fonctionnels sont une méthode simple et efficace pour créer des interfaces utilisateur dans React. Grâce aux hooks comme useState, ils peuvent également gérer l'état et devenir encore plus puissants. Maintenant que vous comprenez comment ils fonctionnent, vous pouvez commencer à créer vos propres composants réutilisables.

2. Composants Basés sur des Classes

Avant l'introduction des hooks dans React 16.8, les composants basés sur des classes étaient la méthode principale pour créer des composants qui gèrent un état ou interagissent avec le cycle de vie de React. Bien que les composants fonctionnels soient maintenant privilégiés, il est important de comprendre comment fonctionnent les composants basés sur des classes, car ils sont encore largement utilisés dans de nombreux projets existants.

Qu'est-ce qu'un Composant Basé sur une Classe ?

Un composant basé sur une classe est une classe JavaScript qui hérite de React.Component. Il possède plusieurs caractéristiques distinctives :

  • État local : Les composants basés sur des classes peuvent avoir leur propre état grâce à la propriété this.state.
  • Cycle de vie : Ils permettent d'utiliser des méthodes spéciales appelées "méthodes de cycle de vie" (par exemple, componentDidMount, componentDidUpdate, etc.).
  • Contexte (this) explicite : Contrairement aux composants fonctionnels, vous devez souvent lier explicitement les fonctions au contexte this.

Exemple Simple : Création d'un Composant Basé sur une Classe

Voici un exemple simple d'un composant basé sur une classe qui affiche un message personnalisé :

📋 Copier le code

class Bonjour extends React.Component {
render() {
return <h1>Bonjour, {this.props.nom} !</h1>;
}
}

ReactDOM.render(<Bonjour nom="Alice" />, document.getElementById('root'));

Explication ligne par ligne :

  1. class Bonjour extends React.Component { ... } :
    • Cette ligne définit une classe JavaScript appelée Bonjour qui hérite de React.Component. Tous les composants basés sur des classes doivent étendre cette classe de base.
  2. render() { ... } :
    • Toute classe React doit inclure une méthode render(). Cette méthode retourne ce que le composant doit afficher à l'écran sous forme de JSX.
  3. return <h1>Bonjour, {this.props.nom} !</h1>; :
    • Cette ligne retourne du JSX contenant un élément <h1>.
    • {this.props.nom} insère dynamiquement la valeur de la prop nom passée au composant.
  4. ReactDOM.render(<Bonjour nom="Alice" />, document.getElementById('root')); :
    • Cette ligne rend le composant Bonjour dans l'élément HTML ayant l'id root.
    • <Bonjour nom="Alice" /> passe la valeur "Alice" comme prop nom au composant.

Composants Basés sur des Classes avec État

Les composants basés sur des classes peuvent également gérer leur propre état via la propriété this.state. Voici un exemple d'un compteur utilisant un composant basé sur une classe :

📋 Copier le code

class Compteur extends React.Component {
constructor(props) {
super(props);
this.state = { compte: 0 }; // Initialisation de l'état
}

handleClick = () => {
this.setState({ compte: this.state.compte + 1 }); // Mise à jour de l'état
};

render() {
return (
<div>
	<p>Vous avez cliqué {this.state.compte} fois.</p>
	<button onClick={this.handleClick}>
		Cliquez ici
	</button>
</div>
);
}
}

ReactDOM.render(<Compteur />, document.getElementById('root'));

Explication détaillée :

  1. class Compteur extends React.Component { ... } :
    • Nous créons une classe appelée Compteur qui hérite de React.Component.
  2. constructor(props) { ... } :
    • Le constructeur est une méthode spéciale appelée lorsqu'une instance de la classe est créée.
    • super(props) : Appel obligatoire pour initialiser correctement la classe parente React.Component.
    • this.state = { compte: 0 }; : Initialise l'état local du composant avec une propriété compte définie à 0.
  3. handleClick = () => { ... } :
    • Cette ligne définit une fonction fléchée appelée handleClick.
    • Elle utilise this.setState() pour mettre à jour l'état du composant.
    • this.setState({ compte: this.state.compte + 1 }) incrémente la valeur de compte de 1.
  4. render() { ... } :
    • Cette méthode est obligatoire dans tous les composants basés sur des classes.
    • Elle retourne une structure JSX qui décrit ce que le composant doit afficher.
  5. <p>Vous avez cliqué {this.state.compte} fois.</p> :
    • Affiche le nombre actuel de clics stocké dans l'état this.state.compte.
  6. <button onClick={this.handleClick}>Cliquez ici</button> :
    • Ce bouton appelle la fonction handleClick lorsque l'utilisateur clique dessus.
    • onClick={this.handleClick} lie l'événement de clic du bouton à la fonction handleClick.

Pourquoi Utiliser des Composants Basés sur des Classes ?

Les composants basés sur des classes offrent plusieurs avantages, notamment :

  • Gestion de l'état : Ils permettent de gérer facilement l'état local via this.state.
  • Méthodes de cycle de vie : Vous pouvez utiliser des méthodes comme componentDidMount, componentDidUpdate, etc., pour exécuter du code à des moments précis du cycle de vie du composant.
  • Compatibilité rétroactive : Beaucoup de projets React existants utilisent encore des composants basés sur des classes, donc il est important de les connaître même si les composants fonctionnels sont maintenant recommandés.

Exemple Étendu : Gestion de l'État et des Événements

Imaginons que vous souhaitiez créer un composant qui permet à l'utilisateur de changer son prénom en cliquant sur un bouton. Voici comment cela peut être fait :

📋 Copier le code

class Saluer extends React.Component {
constructor(props) {
super(props);
this.state = { nom: "Utilisateur" }; // Initialisation de l'état
}

handleChangeNom(nouveauNom) {
this.setState({ nom: nouveauNom }); // Met à jour l'état
}

render() {
return (
<div>
	<h1>Bonjour, {this.state.nom} !</h1>
	<button onClick={() => this.handleChangeNom("Alice")}>
		Devenir Alice
	</button>
	<button onClick={() => this.handleChangeNom("Bob")}>
		Devenir Bob
	</button>
</div>
);
}
}

ReactDOM.render(<Saluer />, document.getElementById('root'));

Explication détaillée :

  1. class Saluer extends React.Component { ... } :
    • Nous créons une classe appelée Saluer qui hérite de React.Component.
  2. constructor(props) { ... } :
    • Le constructeur initialise l'état du composant avec une propriété nom définie à "Utilisateur".
    • super(props) est nécessaire pour initialiser correctement la classe parente.
  3. handleChangeNom(nouveauNom) { ... } :
    • Cette méthode met à jour la propriété nom de l'état avec une nouvelle valeur.
    • this.setState({ nom: nouveauNom }) met à jour l'état de manière asynchrone.
  4. render() { ... } :
    • Cette méthode retourne une structure JSX contenant un titre <h1> et deux boutons.
    • {this.state.nom} insère dynamiquement la valeur de l'état nom dans le JSX.
  5. <button onClick={() => this.handleChangeNom("Alice")}>Devenir Alice</button> :
    • Lorsque cet événement de clic est déclenché, la méthode handleChangeNom est appelée avec la valeur "Alice".
    • Cela met à jour l'état nom et force React à re-render le composant avec le nouveau nom.

Composants Basés sur des Classes avec Méthodes de Cycle de Vie

Les composants basés sur des classes peuvent également utiliser des méthodes de cycle de vie pour exécuter du code à des moments spécifiques de leur existence. Voici un exemple utilisant componentDidMount :

📋 Copier le code

class Horloge extends React.Component {
constructor(props) {
super(props);
this.state = { date: new Date() }; // Initialisation de l'état avec la date actuelle
}

componentDidMount() {
this.timerID = setInterval(() => {
this.setState({ date: new Date() }); // Met à jour l'état toutes les secondes
}, 1000);
}

componentWillUnmount() {
clearInterval(this.timerID); // Nettoie l'intervalle lorsque le composant est démonté
}

render() {
return (
<div>
	<h1>Heure actuelle :</h1>
	<h2>{this.state.date.toLocaleTimeString()}</h2>
</div>
);
}
}

ReactDOM.render(<Horloge />, document.getElementById('root'));

Explication détaillée :

  1. constructor(props) { ... } :
    • Initialise l'état avec la date actuelle.
  2. componentDidMount() { ... } :
    • Cette méthode est appelée après que le composant a été monté (ajouté au DOM).
    • setInterval(...) crée un intervalle qui met à jour l'état toutes les secondes.
  3. componentWillUnmount() { ... } :
    • Cette méthode est appelée juste avant que le composant soit démonté (retiré du DOM).
    • clearInterval(this.timerID) arrête l'intervalle pour éviter des fuites mémoire.
  4. render() { ... } :
    • Retourne une structure JSX contenant l'heure actuelle extraite de l'état.
    • {this.state.date.toLocaleTimeString()} affiche l'heure mise à jour en temps réel.

Différences entre Composants Fonctionnels et Basés sur des Classes

Voici quelques différences clés entre les deux types de composants :

Aspect Composants Fonctionnels Composants Basés sur des Classes
Syntaxe Plus concise et moderne Plus verbeuse et complexe
État Utilise useState (hook) Utilise this.state
Cycle de vie Utilise des hooks comme useEffect Utilise des méthodes comme componentDidMount et componentWillUnmount
Maintenance Plus facile à maintenir grâce à leur simplicité Peut être plus difficile à maintenir en raison de leur complexité

Conclusion

Les composants basés sur des classes sont une méthode puissante pour créer des composants React, surtout lorsqu'il s'agit de gérer l'état ou d'utiliser des méthodes de cycle de vie. Bien que les composants fonctionnels avec hooks soient désormais privilégiés pour leur simplicité, comprendre les composants basés sur des classes est essentiel pour travailler sur des projets existants ou avancés.

3. Composants Réutilisables

Les composants React sont conçus pour être réutilisables. Voici un exemple où un composant est utilisé plusieurs fois avec des props différentes :

📋 Copier le code

function Saluer({ message, nom }) {
return <p>{message}, {nom} !</p>;
}

function App() {
return (
<div>
<Saluer message="Bonjour" nom="Alice" />
<Saluer message="Salut" nom="Bob" />
</div>
);
}

ReactDOM.render(<App />, document.getElementById('root'));

Explication :

  • function Saluer({ message, nom }) : Définit un composant fonctionnel qui accepte deux props : message et nom.
  • <Saluer message="Bonjour" nom="Alice" /> : Utilise le composant Saluer avec des valeurs spécifiques pour les props.
  • function App() : Composant parent qui utilise plusieurs instances du composant Saluer.

4. Composants avec État

Les composants peuvent également gérer leur propre état. Voici un exemple utilisant useState pour créer un compteur :

📋 Copier le code

import React, { useState } from 'react';

function Compteur() {
const [compte, setCompte] = useState(0);

return (
<div>
<p>Vous avez cliqué {compte} fois.</p>
<button onClick={() => setCompte(compte + 1)}>
	Cliquez ici
</button>
</div>
);
}

ReactDOM.render(<Compteur />, document.getElementById('root'));

Explication :

  • const [compte, setCompte] = useState(0) : Initialise l'état compte avec la valeur 0.
  • setCompte(compte + 1) : Met à jour l'état lorsque le bouton est cliqué.

5. Meilleures Pratiques pour les Composants

Pour écrire des composants React efficaces et maintenables, voici quelques conseils :

  • Gardez les composants petits et modulaires : Divisez votre interface en petits composants réutilisables.
  • Nommez vos composants explicitement : Utilisez des noms descriptifs pour rendre votre code plus lisible.
  • Privilégiez les composants fonctionnels : Ils sont plus simples et performants grâce aux hooks.

Conclusion

Vous avez maintenant appris à créer et utiliser des composants React, qu'ils soient fonctionnels ou basés sur des classes. En combinant des composants réutilisables, vous pouvez construire des interfaces utilisateur complexes et modulaires.

Prochain chapitre : Composants Basés sur des Classes