• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 23/02/2024

Apprivoisez les anciennes syntaxes de React

À l'heure où ce cours a été écrit, nous en sommes à la version 17.0.2 de React. React a effectivement connu de nombreuses évolutions. Cela veut aussi dire que la manière dont on écrit un composant aujourd'hui ne ressemble pas du tout à la manière dont on le faisait au début. On pourrait considérer que ce qui appartient au passé reste dans le passé. Mais ce serait sans compter les codebases qui contiennent des composants écrits dans d'autres syntaxes. Remontons dans notre machine à remonter dans le temps pour voir les grandes étapes de React. 🚀

Découvrez les évolutions principales de React

Au tout débuts : createClass

Lorsque React a été rendu open source en 2013, les composants étaient créés avec React.createClass  . Pour vous donner un exemple, un composant MyComponent  qui reçoit une prop title  se serait écrit de la manière suivante :

React.createClass({
    displayName: "MyComponent",
    render() {
        return (
            <div>
                <h1>{this.props.title}</h1>
            </div>
        )
    }
})

Mais aujourd'hui, cette syntaxe est officiellement considérée comme dépréciée, et vous ne la trouverez nulle part dans la documentation de React.

... En revanche, vous risquez clairement de tomber sur des composants classe.

Le temps des composants classe

Avec l'ajout des classes dans ES 2015 (voici la documentation de Mozilla sur les classes, en anglais), React a voulu s'aligner en créant les composants classe. Il s'agissait à l'époque d'un changement majeur. Durant ce chapitre ainsi que le chapitre suivant, nous allons prendre le temps de revenir sur leur syntaxe, la manière de faire des appels API et de gérer le state et les props dans les composants classe.

Vous êtes invité à découvrir dès maintenant dans le screencast ci-dessous la syntaxe des composants classe. 👇

Si vous voulez voir le code complet de ce composant entier, vous pouvez  le trouver juste ici, sur le repository GitHub.

Découvrez la syntaxe

Comme vous avez pu le voir dans le screencast juste au-dessus, la syntaxe des composants classe est différente. Nous allons ici créer un nouveau composant EmailInput  que nous mettrons dans le footer.

On commence d’abord par déclarer le composant :

import { Component } from 'react'
 
class EmailInput extends Component {
    constructor() {
    }
 
    render() {
        return (
            <div>
                <input />
            </div>
        )
    }
}
 
export default EmailInput

class  et  extends Component   sont ici la manière de déclarer notre composant. Si vous avez déjà manipulé des classes, vous devriez déjà avoir vu extends  et constructor  . Mais sachez que le constructor  , dont vous trouverez la documentation ici, est une méthode qui est utilisée pour créer et initialiser un objet lorsqu'on utilise le mot cléclass .

Mais au fait, c’est quoi ce render  ?!

Eh bien, il s’agit d’une méthode de votre composant. C'est d'ailleurs la seule méthode qui est obligatoirement appelée dans votre composant (et donc qui doit impérativement y figurer). Pour un certain nombre d'événements, votre composant devra être "re-render". À chaque fois, cette méthode va recalculer ce qui y est déclaré, et afficher ce qui est retourné.

Il y aura un nouveau render à chaque fois qu’une mise à jour aura lieu :

  • à l’initialisation du constructor  ;

  • à chaque mise à jour d’une props ;

  • à chaque changement du state (mais nous y reviendrons plus tard).

Effectivement, vous n’avez pas de render  dans les composants fonction.

Notez que render  doit forcément retourner du JSX (ce qui sera dans le return  ). Mais si vous n'avez rien à retourner dans votre render  , vous pouvez également retourner null  .

Accédez aux props

Nous allons ajouter un peu de style au composant que nous venons de créer, en faisant une version pour le darkMode  et une version pour le lightMode  . Sauf que, comme je vous l’ai dit dans le chapitre sur le Contexte, utiliser le Contexte est beaucoup plus simple avec les hooks… Or, on ne peut pas utiliser les hooks depuis les composants classe. On va donc se contenter de passer le theme  en props.

Mais d’ailleurs, ici, on n’a pas de paramètres dans lesquels récupérer les props ? On fait comment pour les récupérer ?

Vous vous en doutez sûrement, il existe également un moyen de les récupérer dans les composants classe. Pour cela, vous pouvez utiliser this.props  partout dans votre composant – que ce soit dans le return  , le render  , ou dans une méthode. On va d’abord les initialiser dans le constructor  , on en profite pour lui passer le state  initial, même si nous n’en avons pas besoin pour le moment (sinon, notre linter va râler).

On déclare donc dans notre composant :

class EmailInput extends Component {
    constructor(props) {
        super(props)
        this.state = {
            inputValue: '',
        }
    }
 
    render() {
    // Ici on récupère theme en destructurant this.props
        const { theme } = this.props
        return (
            <div>
                <input />
            </div>
        )
    }
}

Ce qui va nous permettre de faire un style différent en fonction de notre theme  . Vous pourrez trouver ce style sur P4C1-exercice  .

Mais au fait, c’est quoi ce this  , là ?

Si vous êtes familier de JavaScript, vous connaissez sûrement déjà this  . this  fait référence à l'objet auquel il appartient. Pour rappel, vous pouvez voir comment définir une classe en JavaScript dans le chapitre Définissez des objets et leurs attributs avec des classes du cours Apprenez à programmer avec JavaScript.

Donc, ici, le this  fait référence à notre composant : il s'agit des props  et du state  de EmailInput  .

Mais attention, lorsque vous déclarez des méthodes (qui sont en quelque sorte des fonctions) dans vos composants, il vous faudra faire attention au bind  .

C'est quoi encore ça, le "bind" ?

Déjà, commençons simple : "bind" en traduction littérale veut dire "lier". Cela veut dire qu'on va lier nos méthodes à notre composant classe : il faut qu'elles soient correctement bindées au this  . C'est ce que nous verrons dans quelques instants, une fois que nous aurons utilisé le state  . ✨

Gérez le state avec setState

Nous allons maintenant gérer la valeur qui est saisie dans notre EmailInput  avec setState  .

setState  ... C'est un peu la même chose que useState  , non ?

Eh bien… non. Tout d'abord, useState  est un hook : il s'agit donc de la manière de gérer le state pour les composants fonction. setState  concerne les composants classe. Par ailleurs, si ces deux fonctions concernent toutes les deux le state, elles ne fonctionnent pas de la même manière :

  •  useState  vous permet de déclarer votre variable de state, d'initialiser sa valeur et de récupérer une fonction pour la mettre à jour ;

  • mais setState  permet uniquement de mettre à jour tout le state de notre composant. Souvenez-vous : le state initial est déclaré dans le constructor  .

Pour gérer le state de la valeur saisie dans notre EmailInput  , nous allons devoir procéder par étapes. Si vous avez du mal à suivre, vous pourrez trouver tout le code nécessaire sur le repo GitHub.
Dans la section juste au-dessus, vous aviez initialisé votre state dans le constructor  avec :

this.state = {
    inputValue: '',
}

On va maintenant pouvoir déclarer une fonction pour mettre à jour la valeur de notre state :

updateInputValue = (value) => {
    this.setState({ inputValue: value })
}

Pas besoin de  const =   devant notre fonction. D'habitude, il aurait fallu l'initialiser, mais ici, étant donné que vous êtes dans une classe  , updateInputValue  est une méthode de votre classe EmailInput  .

On aurait pu mettre updateInputValue  dans le render  , non ?

Eh bien, oui. On aurait pu. Mais comme je vous disais, tout ce qui est dans le render  est exécuté à chaque fois qu'une prop, ou que le state, est mis à jour. Ce qui veut dire que notre fonction serait à nouveau déclarée : pas très performant, n'est-ce pas ?

Et cette méthode est appelée dans onChange  de input  :

<input
    onChange={(e) => this.updateInputValue(e.target.value)}
/>

Ici, chaque fois qu'un setState  est effectué, cela va déclencher un nouveau render  de notre composant.

Il existe un certain nombre de règles à respecter pour setState  (le fait que setState  soit asynchrone, que les mises à jour du state soient fusionnées, etc.). Je vous conseille donc de vous renseigner sur ces règles directement dans la documentation de React.

Et de la même manière qu'on a accédé aux props  avec this.props  , c'est this.state  qui nous permet d'accéder au state courant.

Pour afficher le contenu de notre input, on peut donc faire :

render() {
    return (
        <div>
            {this.state.inputValue}
            <input
                onChange={(e) => this.updateInputValue(e.target.value)}
            />
        </div>
    )
}

Revenez au this

D'habitude, lorsque nous déclarons une nouvelle fonction, on utilise la syntaxe  function  myFunction()  . Alors pourquoi ici on a utilisé une fonction fléchée ?

Eh bien, pour pouvoir accéder à votre méthode dans votre classe, vous avez besoin de "binder" votre fonction à votre classe, relier les deux, en quelque sorte. Les fonctions fléchées permettent de le faire de manière implicite. Donc pas d'embêtement ici.

Sans fonction fléchée, autrement, vous auriez dû le faire de manière explicite comme ci-dessous : 👇

constructor(props) {
    super(props)
    this.updateInputValue = this.updateInputValue.bind(this)
    this.state = {
        inputValue: '',
    }
}
 
updateInputValue (value) {
    this.setState({ inputValue: value })
}

Je sais que le this  peut être un peu complexe à saisir. C'est d'ailleurs une des raisons pour lesquelles React a choisi de favoriser les composants fonction, pour éviter cette complexité au moment de l'apprentissage. Mais n'hésitez pas à creuser un peu le sujet si cela reste trop flou pour vous. Par exemple, cet article de blog (en anglais) revient sur quelques notions fondamentales.

Exercez-vous

C'est le moment de mettre en pratique ce que vous venez de voir. Pour cela, j'ai transformé le composant Card  en composant classe, et créé un composant EmptyList  qui permet de signaler à l'utilisateur que la liste de compétences est vide (s'il a répondu non à toutes les questions). Vous allez devoir :

  • recréer le système de favori, qui ajoute des "⭐️" autour du nom du freelance sur lequel on clique dans Card  , en restant sur un composant classe ;

  • "traduire" le composant EmailInput  en composant fonction ;

  • "traduire" le composant EmptyList  en composant fonction.

Comme d'habitude, vous trouverez le début de l'exercice sur la brancheP4C1-begin  , et la solution surP4C1-solution  . Alors à vous de jouer ! 🚀

En résumé

  • Les composants classe sont apparus en même temps que les class  en JavaScript. 

  • Un composant classe est déclaré avec  class NomDuComposant extends Component   .

  • render  est appelé à chaque fois qu’une mise à jour a lieu.

  • Le state est mis à jour avec setState  , auquel on passe un objet en paramètre.

  • On accède aux props et au state avec this.props  et this.state  .

Dans le prochain chapitre, nous verrons un autre aspect essentiel des composants classe : les méthodes de cycle de vie (lifecycle methods), et nous apprendrons à appeler une API dans un composant classe. Alors à tout de suite dans le prochain chapitre ! 🚀

Exemple de certificat de réussite
Exemple de certificat de réussite