Blog
  1. Accueil
  2. Blog
  3. L’art subtil des components React : De novice à maître

L’art subtil des components React : De novice à maître

L’art subtil des components React : De novice à maître
Auteur

Franck Mairot

Publié le
Partager

React est une bibliothèque JavaScript très populaire, développé par la société Méta (anciennement Facebook) pour la conception d’interfaces utilisateur dynamiques, interactives et donc, réactive ! L’une des caractéristiques les plus puissantes et intéressantes de React est l’utilisation de ses components. Les components permettent de diviser l’interface utilisateur en éléments indépendants, modulables et réutilisables afin de faciliter, de fait, l’organisation et la maintenabilité du code source d’un projet web frontend. Ce guide a pour objectif de vous mener de novice à maître dans l’art de créer, gérer et optimiser des components React. Pour en savoir plus sur React, consultez notre article comprendre react.js. N’hésitez pas non plus à découvrir les matchs Vue.js vs React et Angular vs React ! Si vous avez besoin d’aide pour vos projets, consultez notre liste d’agences React pour trouver des experts qualifiés

Les fondamentaux des components React

Qu’est-ce qu’un component React ?

react components - definition

Un component React est une unité de base qui encapsule la logique et le rendu d’une partie de l’interface utilisateur. Il existe deux types de components en React : les components fonctionnels et les composants de classe.

  • Les components fonctionnels : Il s’agit d’une fonction JavaScript qui accepte des props en entrée et retourne et affiche des éléments React. En voici un exemple très basique de component fonctionnel :
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
export default Welcome;

  • Les components de classe : Utilisant la syntaxe ES6, les components de classe offrent plus de fonctionnalités, notamment la gestion de l’état et des méthodes de cycle de vie. Voici un exemple de component de classe :
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
export default Welcome;

Pour rappel, l’installation d’un projet d’application web React peut se faire très simplement et rapidement grâce à l’outil Create React App !

Fonctionnement et utilisation

Les composants peuvent accepter des entrées appelées “props” (ou propriétés) et renvoyer des éléments React qui décrivent ce qui doit apparaître à l’écran. Les props sont des données en lecture seule transmises d’un component parent à un component enfant.

Voici un exemple simple d’utilisation des props en React :

function Greeting(props) {
  return <h1>Bonjour, {props.name}</h1>;
}
export default Greeting;
<Greeting name="John" />;

Création et composition de component

Écrire son premier component

Commençons par créer un component simple qui affiche un message de bienvenue à l’écran. Utilisons une fonction pour définir notre composant :

function Welcome(props) {
  return <h1>Bienvenue, {props.name}!</h1>;
}
export default Welcome;

Ensuite, nous allons importer et utiliser ce composant dans notre application principale :

import React from 'react';
import ReactDOM from 'react-dom';
import Welcome from './Welcome';
ReactDOM.render(<Welcome name="Alice" />, document.getElementById('root'));

Enrichir l’interface avec des composants enfants

Les composants peuvent contenir d’autres composants, créant ainsi une structure hiérarchique. Cela permet de composer des interfaces utilisateur complexes à partir de composants simples et réutilisables.

Exemple de composants enfants :

function App() {
  return (
    <div>
      <Greeting name="Alice" />
      <Greeting name="Bob" />
      <Greeting name="Charlie" />
    </div>
  );
}

Les props dans React et leur utilité

Définition et manipulation des props

Les props sont des arguments passés aux composants React. Ils permettent de transmettre des données d’un composant parent à un composant enfant. Les composants doivent traiter leurs props comme des données en lecture seule.

Voici un exemple simple de passage de props entre deux composants :

function User(props) {
  return <h2>Utilisateur : {props.name}</h2>;
}
export default User;
<User name="John Doe" />;

Passage de données aux composants enfants

Il est recommandé de créer des composants plus petits à partir de composants plus grands pour faciliter la réutilisabilité et la maintenance. Les données peuvent être passées d’un composant parent à un composant enfant via les props.

Voyons un exemple basique de passage de données entre deux composants :

function ParentComponent() {
  const user = { name: 'John Doe', age: 30 };
  return <ChildComponent user={user} />;
}
export default ParentComponent;
function ChildComponent(props) {
  return (
    <div>
      <h1>Nom : {props.user.name}</h1>
      <p>Âge : {props.user.age}</p>
    </div>
  );
}
export default ChildComponent;

Pour gérer ces flux de données plus nombreux sur une application concrète et professionnel, rien ne vaut l’utilisation de React Redux !

Les états des composants (State) et événements

Gestion de l’état interne

L’état (state) est une fonctionnalité qui permet aux composants de réagir aux événements utilisateurs et de changer dynamiquement leur affichage. Chaque composant a plusieurs méthodes de cycle de vie que l’on peut surcharger pour exécuter du code à des moments précis.

Utilisation du hook useState()

Le hook useState() est une fonction React utilisée pour ajouter l’état aux composants fonctionnels. Voici un exemple d’utilisation de useState :

import React, { useState } from 'react';
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Vous avez cliqué {count} fois</p>
      <button onClick={() => setCount(count + 1)}>Cliquez ici</button>
    </div>
  );
}
export default Counter;

Dans cet exemple, useState() initialise une variable d’état count à 0 et renvoie une paire de valeurs : l’état actuel (count) et une fonction de mise à jour de l’état (setCount).

Gestion des états complexes

Lorsque l’état devient plus complexe, par exemple un objet ou un tableau, vous pouvez toujours utiliser useState(). Cependant, la mise à jour de l’état nécessitera souvent une approche plus soignée pour éviter de remplacer l’état entier.

import React, { useState } from 'react';
function Profile() {
  const [profile, setProfile] = useState({
    name: 'John Doe',
    age: 30,
    email: '[email protected]'
  });
  function updateEmail(newEmail) {
    setProfile(prevProfile => ({ ...prevProfile, email: newEmail }));
  }
  return (
    <div>
      <h1>Nom: {profile.name}</h1>
      <p>Âge: {profile.age}</p>
      <p>Email: {profile.email}</p>
      <button onClick={() => updateEmail('[email protected]')}>Mettre à jour l'email</button>
    </div>
  );
}
export default Profile;

Utilisation du hook useReducer()

Pour des états encore plus complexes ou pour mieux gérer les mises à jour d’état impliquant de nombreuses transitions, le hook useReducer() peut être utilisé. useReducer() est particulièrement utile lorsque la logique d’état est complexe et implique plusieurs sous-valeurs.

import React, { useReducer } from ‘react’;
const initialState = { count: 0 };
function reducer(state, action) {
  switch (action.type) {
    case ‘increment’:
      return { count: state.count + 1 };
    case ‘decrement’:
      return { count: state.count – 1 };
    default:
      throw new Error();
  }

}

function Counter() {

  const [state, dispatch] = useReducer(reducer, initialState);

  return (
      <p>Compteur : {state.count}</p>

      <button onClick={() => dispatch({ type: ‘increment’ })}>+</button>

      <button onClick={() => dispatch({ type: ‘decrement’ })}>-</button>

    </div>
  );
}
export default Counter;

Interaction avec les événements

Les événements comme les clics de bouton ou les entrées de texte peuvent être gérés dans React de manière similaire aux événements DOM natifs habituellement gérés par JavaScript.

Les événements, en React, sont, en réalité, des objets synthétiques qui encapsulent les événements natifs du DOM, fournissant une interface cohérente entre les différents navigateurs web.

Exemple de gestion des événements :

function ButtonComponent() {
  function handleClick() {
    alert('Button clicked!');
  }
  return <button onClick={handleClick}>Cliquez ici</button>;
}
export default ButtonComponent;

Lorsque vous gérez des événements sur plusieurs éléments, il peut être utile d’identifier quel élément a déclenché l’événement en question. Par exemple, si vous avez une liste de boutons et que vous voulez savoir lequel a été cliqué, vous pouvez utiliser un attribut personnalisé ou bien l’indice de l’élément.

function ListComponent() {
  const items = ['Item 1', 'Item 2', 'Item 3'];
  function handleClick(index) {
    alert(`You clicked on ${items[index]}`);
  }
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>
          <button onClick={() => handleClick(index)}>{item}</button>
        </li>
      ))}
    </ul>
  );
}
export default ListComponent;

Utilisation avancée des composants

Logique conditionnelle dans les composants

Il est possible d’implémenter des logiques conditionnelles dans vos composants React pour afficher ou masquer certains éléments en fonction des valeurs de l’état ou des props.

Exemple de logique conditionnelle :

function LoginControl(props) {

  const isLoggedIn = props.isLoggedIn;

  if (isLoggedIn) {

    return <LogoutButton />;

  } else {

    return <LoginButton />;

  }

}

export default LoginControl;

Gestion de formulaires et listes dynamiques

Créer et gérer des formulaires dans React est une tâche courante. Les listes dynamiques permettent d’afficher des collections d’éléments de manière interactive.

Voyons un exemple basique de formulaire conçu à l’aide React :

import React, { useState } from ‘react’;

function NameForm() {

  const [name, setName] = useState(”);

  function handleChange(event) {

    setName(event.target.value);

  }

  function handleSubmit(event) {

    alert(‘Un nom a été soumis : ‘ + name);

    event.preventDefault();

  }

  return (

    <form onSubmit={handleSubmit}>

      <label>

        Nom :

        <input type=”text” value={name} onChange={handleChange} />

      </label>

      <button type=”submit”>Envoyer</button>

    </form>

  );

}

export default NameForm;

Voyons maintenant un exemple de gestion d’une liste dynamique :

import React, { useState } from ‘react’;

function TodoList() {

  const [items, setItems] = useState([]);

  const [text, setText] = useState(”);

  function handleChange(event) {

    setText(event.target.value);

  }

  function handleSubmit(event) {

    event.preventDefault();

    setItems([…items, { text, id: Date.now() }]);

    setText(”);

  }

  return (

    <div>

      <h3>TODO</h3>

      <form onSubmit={handleSubmit}>

        <input onChange={handleChange} value={text} />

        <button type=”submit”>Ajouter #{items.length + 1}</button>

      </form>

      <ul>

        {items.map(item => (

          <li key={item.id}>{item.text}</li>

        ))}

      </ul>

    </div>

  );

}

export default TodoList;

Cycle de vie d’un composant React

Montage et démontage

Les composants de classe offrent davantage de fonctionnalités avec les méthodes de cycle de vie des composants telles que componentDidMount(), componentDidUpdate() et componentWillUnmount(). Ces méthodes permettent d’exécuter du code à des moments précis du cycle de vie d’un composant React.

Découvrons un exemple illustrant l’utilisation du cycle de vie du composant Timer :

class Timer extends React.Component {

  constructor(props) {
    super(props);
    this.state = { seconds: 0 };
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  tick() {
    this.setState((state) => ({
      seconds: state.seconds + 1,
    }));
  }

  render() {
    return <div>Secondes : {this.state.seconds}</div>;
  }

}

Les hooks de cycle de vie

Avec les hooks, vous pouvez gérer le cycle de vie des composants fonctionnels sans utiliser les classes. Par exemple, useEffect() remplace les méthodes de cycle de vie des composants componentDidMount(), componentDidUpdate() et componentWillUnmount().

Voici un exemple concret de l’utilisation du hook useEffect() :

import React, { useState, useEffect } from 'react';

function Timer() {

  const [seconds, setSeconds] = useState(0);

  useEffect(() => {

    const interval = setInterval(() => {

      setSeconds((s) => s + 1);

    }, 1000);

    return () => clearInterval(interval);

  }, []);

  return <div>Secondes : {seconds}</div>;

}

Optimisation des composants

Performance et bonnes pratiques

Optimiser les composants React est crucial pour maintenir des applications performantes. Découvrons quelques bonnes pratiques incluent :

  • Éviter de redéfinir les fonctions à chaque rendu,
  • Utiliser des clés uniques pour les éléments de liste,
  • Minimiser le nombre de re-rendus inutiles.

Utilisation des PureComponent et React.memo

PureComponent et React.memo sont utilisés pour optimiser les performances en évitant les re-rendus inutiles.

Exemple du composant basique avec PureComponent :

class MyComponent extends React.PureComponent {

  render() {

    return <div>{this.props.text}</div>;

  }

}

Découvrons un premier exemple d’utilisation de React.memo :

const MyFunctionalComponent = React.memo(function MyFunctionalComponent(props) {

  return <div>{props.text}</div>;

});

Dans ce guide, nous avons exploré en détail les composants React, leur création, gestion et optimisation. Nous avons vu comment utiliser les props et l’état pour rendre des interfaces dynamiques et comment tirer parti des react hooks et des composants de classe pour gérer le cycle de vie des composants. En appliquant ces concepts, vous pouvez créer des applications React robustes et performantes mais également stylisées avec React UI.

Pour continuer à améliorer vos compétences en React, consultez nos articles sur WordPress et React.js, React Native vs React.js et SEO pour React. Bonne chance dans vos projets de développement avec React !