Piège

Nous vous conseillons de définir vos composants au moyen de fonctions plutôt que de classes. Voyez comment migrer.

Component est la classe de base pour les composants React définis à l’aide de classes JavaScript. Les composants à base de classes restent pris en charge par React, mais nous les déconseillons pour tout nouveau code.

class Greeting extends Component {
render() {
return <h1>Salut {this.props.name} !</h1>;
}
}

Référence

Component

Pour définir un composant React sous forme de classe, étendez la classe Component fournie par React et définissez sa méthode render :

import { Component } from 'react';

class Greeting extends Component {
render() {
return <h1>Salut {this.props.name} !</h1>;
}
}

Seule la méthode render est requise, les autres méthodes sont optionnelles.

Voir d’autres exemples ci-dessous.


context

Le contexte d’un composant à base de classe est mis à disposition dans this.context. Il n’est disponible que si vous précisez quel contexte vous souhaitez récupérer en utilisant static contextType (approche plus récente) ou static contextTypes (approche dépréciée).

Un composant à base de classe ne peut lire qu’un contexte à la fois.

class Button extends Component {
static contextType = ThemeContext;

render() {
const theme = this.context;
const className = 'button-' + theme;
return (
<button className={className}>
{this.props.children}
</button>
);
}
}

Remarque

La lecture de this.context dans des composants à base de classes est équivalente à un appel à useContext dans les fonctions composants.

Voyez comment migrer.


props

Les props passées à un composant à base de classe sont mises à disposition dans this.props.

class Greeting extends Component {
render() {
return <h1>Salut {this.props.name} !</h1>;
}
}

<Greeting name="Clara" />

Remarque

La lecture de this.props dans des composants à base de classes est équivalente à la déclaration des props dans les fonctions composants.

Voyez comment migrer.


refs

Dépréciation

Cette API sera retirée d’une future version majeure de React. Utilisez plutôt createRef.

Vous permet d’accéder à des refs textuelles historiques pour ce composant.


state

L’état d’un composant à base de classe est mis à disposition dans this.state. La champ state doit être un objet. Ne modifiez pas l’état directement. Si vous souhaitez modifier l’état, appelez setState avec un objet d’état en argument.

class Counter extends Component {
state = {
age: 31,
};

handleAgeChange = () => {
this.setState({
age: this.state.age + 1
});
};

render() {
return (
<>
<button onClick={this.handleAgeChange}>
Prendre de l’âge
</button>
<p>Vous avez {this.state.age} ans.</p>
</>
);
}
}

Remarque

La définition de state dans les composants à base de classes est équivalente à l’appel de useState dans les fonctions composants.

Voyez comment migrer.


constructor(props)

Le constructeur est exécuté avant le montage (l’ajout dans le DOM) de votre composant. En général, vous n’utilisez un constructeur dans React que pour deux raisons. Il vous permet de déclarer votre état puis de lier certaines de vos méthodes à votre instance :

class Counter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
// ...
}

Si vous utilisez une syntaxe JavaScript moderne, vous aurez rarement besoin des constructeurs. Vous pouvez plutôt réécrire le code ci-dessus en utilisant des initialiseurs de champs d’instance qui sont pris en charge par tous les navigateurs modernes et par des outils comme Babel :

class Counter extends Component {
state = { counter: 0 };

handleClick = () => {
// ...
}

Un constructeur ne devrait contenir aucun effet de bord ni aucun abonnement.

Paramètres

  • props : les props initiales du composant.

Valeur renvoyée

constructor ne devrait rien renvoyer.

Limitations

  • Ne lancez aucun effet de bord et ne souscrivez aucun abonnement dans le constructeur. Utilisez plutôt componentDidMount pour ça.

  • Dans un constructeur, vous devez impérativement appeler super(props) avant toute autre instruction. Si vous ne le faites pas, this.props sera undefined pendant l’exécution du constructeur, ce qui peut être déroutant et causer des bugs.

  • Le constructeur est le seul endroit où vous pouvez affecter une valeur directement à this.state. Dans toutes les autres méthodes, vous devez plutôt utiliser this.setState(). En revanche, n’appelez pas setState dans le constructeur.

  • Lorsque vous faites du rendu côté serveur, le constructeur sera exécuté côté serveur aussi, suivi de la méthode render. En revanche, les méthodes de cycle de vie telles que componentDidMount ou componentWillUnmount ne seront pas exécutées côté serveur.

  • En mode strict, React appellera votre constructor deux fois en développement, puis jettera une des instances obtenues. Ce comportement vous permet de repérer des effets de bord involontaires qui doivent être sortis du constructor.

Remarque

Il n’y a pas d’équivalent réel du constructor dans les fonctions composants. Pour déclarer un état dans une fonction composant, utilisez useState. Pour éviter de recalculer l’état initial, passez une fonction à useState.


componentDidCatch(error, info)

Si vous définissez componentDidCatch, React l’appellera lorsqu’un composant descendant lèvera une erreur lors du rendu. Ça vous permettra de signaler l’erreur à un service de supervision en production.

Elle est en général utilisée conjointement avec static getDerivedStateFromError, qui vous permet de mettre à jour l’état en réaction à une erreur afin d’afficher un message d’erreur à l’utilisateur. Un composant doté de ces méthodes est ce qu’on appelle un périmètre d’erreur.

Voir un exemple.

Paramètres

  • error : l’erreur qui a été levée. En pratique il s’agira généralement d’une instance d’Error, mais ce n’est pas garanti parce que JavaScript autorise un throw de n’importe quelle valeur, y compris des chaînes de caractères et même null.

  • info : un objet contenant des informations complémentaires sur l’erreur. Son champ componentStack contient une pile d’appel de rendu avec le composant ayant levé l’erreur, ainsi que les noms et emplacements dans le code source de tous ses composants parents. En production, les noms des composants seront minifiés. Si vous mettez en place un signalement d’erreurs en production, vous pouvez décoder la pile d’appels de rendu grâce aux sourcemaps, exactement comme pour les piles d’appels d’erreurs JavaScript usuelles.

Valeur renvoyée

componentDidCatch ne devrait rien renvoyer.

Limitations

  • Par le passé, on appelait couramment setState dans componentDidCatch pour mettre à jour l’UI et afficher un message d’erreur de remplacement. C’est déprécié en faveur d’une définition de static getDerivedStateFromError.

  • Les builds de production et de développement diffèrent légèrement dans leur gestion de l’erreur par componentDidCatch. En développement, les erreurs se propageront jusqu’à window, ce qui signifie que window.onerror et window.addEventListener('error', callback) intercepteront les erreurs attrapées par componentDidCatch. En production, les erreurs ne seront pas propagées, de sorte que les gestionnaires d’erreurs placés plus haut dans l’arbre ne recevront que les erreurs qui n’auront pas été expressément interceptées par componentDidCatch.

Remarque

Il n’y a pas encore d’équivalent direct à componentDidCatch dans les fonctions composants. Si vous souhaitez éviter de créer des composants à base de classes, écrivez un unique composant ErrorBoundary comme ci-dessus et utilisez-le dans toute votre appli. Vous pouvez aussi utiliser le module react-error-boundary qui fait ça (et davantage) pour vous.


componentDidMount()

Si vous définissez la méthode componentDidMount, React l’appellera lorsque votre composant sera ajouté au DOM (monté). C’est l’endroit classique pour démarrer un chargement de données, souscrire des abonnements, ou manipuler des nœuds du DOM.

Si vous implémentez componentDidMount, vous aurez généralement besoin d’implémenter d’autres méthodes de cycle de vie pour éviter les bugs. Si par exemple componentDidMount lit de l’état et des props, vous devrez aussi implémenter componentDidUpdate pour en gérer les modifications, et componentWillUnmount pour nettoyer toute mise en place effectuée par componentDidMount.

class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};

componentDidMount() {
this.setupConnection();
}

componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}

componentWillUnmount() {
this.destroyConnection();
}

// ...
}

Voir d’autres exemples.

Paramètres

componentDidMount ne prend aucun paramètre.

Valeur renvoyée

componentDidMount ne devrait rien renvoyer.

Limitations

  • En mode strict, en développement React appellera componentDidMount, puis appellera immédiatement componentWillUnmount et rappellera componentDidMount une seconde fois. Ça vous aide à remarquer un oubli d’implémentation de componentWillUnmount, ou un « miroir » insuffisant dans celle-ci de la logique présente dans componentDidMount.

  • Même si vous pourriez appeler immédiatement setState dans componentDidMount, il est préférable de l’éviter autant que possible. Ça déclencherait un rendu supplémentaire, qui arriverait toutefois avant que le navigateur n’ait mis à jour l’affichage. Ça garantit que même si la méthode render est bien appelée deux fois dans un tel cas, l’utilisateur ne verra pas l’état intermédiaire. Utilisez cette approche avec précaution, parce qu’elle nuit aux performances. La plupart du temps, vous devriez pouvoir plutôt définir l’état initial dans le constructor. Ça reste toutefois utile pour des cas comme les boîtes de dialogue modales et les infobulles, qui nécessitent une mesure de nœud DOM avant de pouvoir afficher quelque chose qui dépend de leur taille ou de leur position.

Remarque

Dans de nombreux cas, définir componentDidMount, componentDidUpdate et componentWillUnmount conjointement dans des composants à base de classes revient à un simple appel à useEffect dans les fonctions composants. Dans les rares cas où il est important d’exécuter du code avant l’affichage par le navigateur, un meilleur équivalent serait useLayoutEffect.

Voyez comment migrer.


componentDidUpdate(prevProps, prevState, snapshot?)

Si vous définissez la méthode componentDidUpdate, React l’appellera immédiatement après que le composant a recalculé son rendu et mis à jour ses props et son état. Cette méthode n’est pas appelée lors du rendu initial.

Vous pouvez l’utiliser pour manipuler le DOM après une mise à jour. C’est également un endroit courant pour des requêtes réseau, du moment que vous comparez les nouvelles props aux anciennes (une requête réseau pourrait par exemple être superflue si les props n’ont pas bougé). En général, vous l’utiliserez conjointement à componentDidMount et componentWillUnmount :

class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};

componentDidMount() {
this.setupConnection();
}

componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}

componentWillUnmount() {
this.destroyConnection();
}

// ...
}

Voir d’autres exemples.

Paramètres

  • prevProps : les props de votre composant avant la mise à jour. Comparez prevProps à this.props pour déterminer ce qui a changé.

  • prevState : l’état de votre composant avant la mise à jour. Comparez prevState à this.state pour déterminer ce qui a changé.

  • snapshot : si vous avez implémenté getSnapshotBeforeUpdate, snapshot contiendra la valeur que vous aviez renvoyée depuis cette méthode. Dans les autres cas, ça vaudra undefined.

Valeur renvoyée

componentDidUpdate ne devrait rien renvoyer.

Limitations

  • componentDidUpdate ne sera pas appelée si shouldComponentUpdate est définie et renvoie false.

  • La logique dans componentDidUpdate devrait généralement être entourée de conditions comparant this.props et prevProps, ainsi que this.state et prevState. Faute de quoi vous risquez des boucles de rendu infinies.

  • Même si vous pourriez appeler immédiatement setState dans componentDidMount, il est préférable de l’éviter autant que possible. Ça déclencherait un rendu supplémentaire, qui arriverait toutefois avant que le navigateur n’ait mis à jour l’affichage. Ça garantit que même si la méthode render est bien appelée deux fois dans un tel cas, l’utilisateur ne verra pas l’état intermédiaire. Cette approche peut nuire aux performances, mais reste toutefois utile pour des cas comme les boîtes de dialogue modales et les infobulles, qui nécessitent une mesure de nœud DOM avant de pouvoir afficher quelque chose qui dépend de leur taille ou de leur position.

Remarque

Dans de nombreux cas, définir componentDidMount, componentDidUpdate et componentWillUnmount conjointement dans des composants à base de classes revient à un simple appel à useEffect dans les fonctions composants. Dans les rares cas où il est important d’exécuter du code avant l’affichage par le navigateur, un meilleur équivalent serait useLayoutEffect.

Voyez comment migrer.


componentWillMount()

Dépréciation

Cette API a été renommée de componentWillMount en UNSAFE_componentWillMount. L’ancien nom est déprécié. Dans les futures versions de React, seul le nouveau nom fonctionnera.

Exécutez le codemod rename-unsafe-lifecycles pour mettre automatiquement le code de vos composants à jour.


componentWillReceiveProps(nextProps)

Dépréciation

Cette API a été renommée de componentWillReceiveProps en UNSAFE_componentWillReceiveProps. L’ancien nom est déprécié. Dans les futures versions de React, seul le nouveau nom fonctionnera.

Exécutez le codemod rename-unsafe-lifecycles pour mettre automatiquement le code de vos composants à jour.


componentWillUpdate(nextProps, nextState)

Dépréciation

Cette API a été renommée de componentWillUpdate en UNSAFE_componentWillUpdate. L’ancien nom est déprécié. Dans les futures versions de React, seul le nouveau nom fonctionnera.

Exécutez le codemod rename-unsafe-lifecycles pour mettre automatiquement le code de vos composants à jour.


componentWillUnmount()

Si vous définissez la méthode componentWillUnmount, React l’appellera avant que votre composant soit retiré du DOM (démonté). C’est un endroit courant pour annuler les chargements de données et vous désabonner.

La logique dans componentWillUnmount devrait agir « en miroir » de celle dans componentDidMount. Si par exemple componentDidMount souscrit un abonnement, componentWillUnmount devrait faire le désabonnement associé. Si la logique de nettoyage dans votre componentWillUnmount lit des props ou de l’état, vous aurez généralement besoin d’implémenter également componentDidUpdate pour nettoyer les ressources (tels que les abonnements) correspondant aux anciennes props et anciens états.

class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};

componentDidMount() {
this.setupConnection();
}

componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}

componentWillUnmount() {
this.destroyConnection();
}

// ...
}

Voir d’autres exemples.

Paramètres

componentWillUnmount ne prend aucun paramètre.

Valeur renvoyée

componentWillUnmount ne devrait rien renvoyer.

Limitations

  • En mode strict, en développement React appellera componentDidMount, puis appellera immédiatement componentWillUnmount et rappellera componentDidMount une seconde fois. Ça vous aide à remarquer un oubli d’implémentation de componentWillUnmount, ou un « miroir » insuffisant dans celle-ci de la logique présente dans componentDidMount.

Remarque

Dans de nombreux cas, définir componentDidMount, componentDidUpdate et componentWillUnmount conjointement dans des composants à base de classes revient à un simple appel à useEffect dans les fonctions composants. Dans les rares cas où il est important d’exécuter du code avant l’affichage par le navigateur, un meilleur équivalent serait useLayoutEffect.

Voyez comment migrer.


forceUpdate(callback?)

Force un composant à recalculer son rendu.

Vous n’en avez normalement pas besoin. Si la méthode render de votre composant se contente de lire this.props, this.state ou this.context, il refera automatiquement son rendu lorsque vous appelez setState dans votre composant ou dans un de ses parents. En revanche, si la méthode render de votre composant lit directement une source de données extérieure, vous devrez demander à React de mettre à jour l’interface utilisateur lorsque cette source de données change. C’est ce à quoi sert forceUpdate.

Essayez d’éviter tout utilisation de forceUpdate, en ne lisant que this.props et this.state dans render.

Paramètres

  • callback optionnel : s’il est précisé, React appellera le callback que vous avez fourni une fois la mise à jour retranscrite dans le DOM.

Valeur renvoyée

forceUpdate ne renvoie rien.

Limitations

Remarque

Là où les composants à base de classes lisent une source de données extérieure pour ensuite forcer avec forceUpdate le recalcul de leur rendu lorsque celle-ci change, les fonctions composants utilisent plutôt useSyncExternalStore.


getChildContext()

Dépréciation

Cette API sera retirée d’une future version majeure de React. Utilisez plutôt Context.Provider.

Vous permet de spécifier les valeurs fournies par le composant pour les contextes historiques.


getSnapshotBeforeUpdate(prevProps, prevState)

Si vous implémentez getSnapshotBeforeUpdate, React l’appellera juste avant de mettre à jour le DOM. Ça permet à votre composant de capturer certaines informations issues du DOM (telles que la position de défilement) avant qu’elles risquent d’évoluer. Toute valeur renvoyée par cette méthode de cycle de vie sera passée en paramètre à componentDidUpdate.

Vous pouvez par exemple l’utiliser dans une UI de type fil de discussion qui aurait besoin de préserver la position de défilement lors des mises à jour :

class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}

getSnapshotBeforeUpdate(prevProps, prevState) {
// Ajoute-t-on des nouveaux éléments à la liste ?
// Capturons alors la position de défilement pour l’ajuster
// par la suite.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}

componentDidUpdate(prevProps, prevState, snapshot) {
// Si nous avons une valeur capturée, c’est qu’on a ajouté
// de nouveaux éléments. On ajuste alors le défilement de façon
// à ce que les nouveaux éléments ne décalent pas les anciens
// hors de la zone visible.
// (Ici `snapshot` est la valeur renvoyée `getSnapshotBeforeUpdate`.)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}

render() {
return (
<div ref={this.listRef}>{/* ...contenu... */}</div>
);
}
}

Dans l’exemple ci-dessus, il est vital de lire la propriété scrollHeight directement dans getSnapshotBeforeUpdate. On ne pourrait pas la lire de façon fiable dans render, UNSAFE_componentWillReceiveProps ou UNSAFE_componentWillUpdate parce qu’il existe un risque de décalage temporel entre les appels de ces méthodes et la mise à jour du DOM par React.

Paramètres

  • prevProps : les props de votre composant avant la mise à jour. Comparez prevProps à this.props pour déterminer ce qui a changé.

  • prevState : l’état de votre composant avant la mise à jour. Comparez prevState à this.state pour déterminer ce qui a changé.

Valeur renvoyée

Vous devriez renvoyer une valeur capturée de quelque type que ce soit, voire null. La valeur que vous renvoyez sera passée en troisième argument à componentDidUpdate.

Limitations

Remarque

Il n’y a pas encore d’équivalent direct à getSnapshotBeforeUpdate dans les fonctions composants. C’est un cas d’usage très rare, mais si vous en avez absolument besoin, vous devrez pour le moment écrire un composant à base de classe.


render()

La méthode render est la seule méthode obligatoire dans un composant à base de classe.

La méthode render devrait spécifier ce que vous souhaitez afficher à l’écran, par exemple :

import { Component } from 'react';

class Greeting extends Component {
render() {
return <h1>Salut {this.props.name} !</h1>;
}
}

React est susceptible d’appeler render à tout moment, aussi vous ne devriez pas supposer son exécution à un moment particulier. En général, la méthode render devrait renvoyer un contenu JSX, mais certains autres types de résultats (comme les chaînes de caractères) sont autorisés. Pour calculer le JSX renvoyé, la méthode render peut lire this.props, this.state et this.context.

Vous devriez écrire la méthode render sous forme de fonction pure, c’est-à-dire qu’elle devrait toujours renvoyer le même résultat si les props, l’état et le contexte n’ont pas changé. Elle ne devrait par ailleurs pas contenir d’effets de bord (tels que des souscriptions d’abonnements) ou interagir avec des API du navigateur. Les effets de bord sont censés survenir soit dans des gestionnaires d’événements, soit dans des méthodes commecomponentDidMount.

Paramètres

render ne prend aucun paramètre.

Valeur renvoyée

render peut renvoyer n’importe quel nœud React valide. Ça inclut les éléments React tels que <div />, les chaînes de caractères, les nombres, les portails, les nœuds vides (null, undefined, true et false) et les tableaux de nœuds React.

Limitations

  • render devrait être écrite comme une fonction pure des props, de l’état et du contexte. Elle ne devrait comporter aucun effet de bord.

  • render ne sera pas appelée si shouldComponentUpdate est définie et renvoie false.

  • En mode strict, React appellera render deux fois en développement et jettera un des résultats. Ça vous permet de repérer des effets de bord involontaires qui doivent être sortis de render.
  • Il n’y a pas de correspondance directe entre l’appel à render et les appels ultérieurs à componentDidMount et componentDidUpdate. Certains résultats d’appels à render sont susceptibles d’être ignorés par React lorsque ça présente un avantage.

setState(nextState, callback?)

Appelez setState pour mettre à jour l’état de votre composant React.

class Form extends Component {
state = {
name: 'Clara',
};

handleNameChange = (e) => {
const newName = e.target.value;
this.setState({
name: newName
});
}

render() {
return (
<>
<input value={this.state.name} onChange={this.handleNameChange} />
<p>Salut {this.state.name}.</p>
</>
);
}
}

setState maintient une file d’attente de modifications à apporter à l’état du composant. Elle indique à React que ce composant et ses enfants doivent recalculer leur rendu avec un nouvel état. C’est le principal moyen de mettre à jour l’interface utilisateur suite à des interactions.

Piège

Appeler setState ne change pas l’état actuel pour le code en cours d’exécution :

function handleClick() {
console.log(this.state.name); // « Clara »
this.setState({
name: 'Juliette'
});
console.log(this.state.name); // Toujours « Clara » !
}

Ça affecte uniquement ce que vaudra this.state à partir du prochain rendu.

Vous pouvez aussi passer une fonction à setState. Ça vous permet de mettre à jour l’état sur base de sa valeur précédente :

handleIncreaseAge = () => {
this.setState(prevState => {
return {
age: prevState.age + 1
};
});
}

Vous n’êtes pas obligé·e de faire ça, mais c’est pratique lorsque vous souhaitez accumuler plusieurs mises à jour de l’état au sein d’un même événement.

Paramètres

  • nextState : soit un objet, soit une fonction.

    • Si vous passez un objet comme nextState, il sera superficiellement fusionné dans this.state.
    • Si vous passez une fonction comme nextState, elle sera traitée comme une fonction de mise à jour. Elle doit être pure, doit accepter l’état en attente et les props comme arguments, et doit renvoyer un objet qui sera superficiellement fusionné dans this.state. React placera votre fonction de mise à jour dans une file d’attente puis refera le rendu de votre composant. Lors du prochain rendu, React calculera le prochain état en appliquant successivement toutes les fonctions de mise à jour en attente, en partant de l’état précédent.
  • callback optionnel : s’il est précisé, React appellera le callback que vous avez fourni une fois la mise à jour retranscrite dans le DOM.

Valeur renvoyée

setState ne renvoie rien.

Limitations

  • Pensez à setState comme à une requête plutôt qu’une commande de mise à jour immédiate du composant. Lorsque plusieurs composants mettent à jour leurs états en réaction à un événement, React regroupe leurs mises à jour et refait leurs rendus en une unique passe, à la fin de l’événement. Pour les rares cas où vous auriez besoin de forcer une mise à jour d’état spécifique à être appliquée de façon synchrone, vous pourriez l’enrober dans flushSync, mais ça gâche généralement la performance.

  • setState ne met pas immédiatement à jour this.state. Il est donc piégeux de lire this.state juste après avoir appelé setState. Utilisez plutôt componentDidUpdate ou l’argument callback de setState, qui vous garantissent tous les deux une exécution après que la mise à jour a été appliquée. Si vous avez besoin de mettre à jour l’état sur base de l’état précédent, vous pouvez passer une fonction pour nextState, comme décrit plus haut.

Remarque

Appeler setState dans les composants à base de classe est similaire à l’appel d’une fonction set dans les fonctions composants.

Voyez comment migrer.


shouldComponentUpdate(nextProps, nextState, nextContext)

Si vous définissez shouldComponentUpdate, React l’appellera pour déterminer s’il peut éviter de calculer un nouveau rendu.

Si vous êtes certain·e de vouloir écrire ça vous-même, vous pouvez comparer this.props avec nextProps et this.state avec nextState et renvoyer false pour indiquer à React que le recalcul du rendu peut être sauté.

class Rectangle extends Component {
state = {
isHovered: false
};

shouldComponentUpdate(nextProps, nextState) {
if (
nextProps.position.x === this.props.position.x &&
nextProps.position.y === this.props.position.y &&
nextProps.size.width === this.props.size.width &&
nextProps.size.height === this.props.size.height &&
nextState.isHovered === this.state.isHovered
) {
// Rien n’a changé, un nouveau rendu est donc superflu
return false;
}
return true;
}

// ...
}

React appelle shouldComponentUpdate avant de refaire le rendu lorsque des nouvelles props ou un nouvel état sont fournis. Ça renvoie par défaut true. Cette méthode n’est pas appelée pour le rendu initial, ni lorsque forceUpdate est utilisée.

Paramètres

  • nextProps : les prochaines props pour le rendu à venir. Comparez nextProps à this.props pour déterminer ce qui a changé.
  • nextState : le prochain état pour le rendu à venir. Comparez nextState à this.state pour déterminer ce qui a changé.
  • nextContext : le prochain contexte pour le rendu à venir. Comparez nextContext à this.context pour déterminer ce qui a changé. N’est disponible que si vous avez spécifié static contextType (approche plus récente) ou static contextTypes (approche dépréciée).

Valeur renvoyée

Renvoie true si vous souhaitez que le composant refasse son rendu. C’est le comportement par défaut.

Renvoie false pour indiquer à React de sauter le recalcul du rendu.

Limitations

  • Cette méthode existe seulement comme une optimisation des performances. Si votre composant ne fonctionne pas sans elle, corrigez-le d’abord.

  • Envisagez de recourir à PureComponent plutôt que d’écrire shouldComponentUpdate à la main. PureComponent fait une comparaison superficielle des props et de l’état, et réduit le risque de sauter une mise à jour utile.

  • Nous vous déconseillons de faire des comparaisons profondes ou d’utiliser JSON.stringify dans shouldComponentUpdate. Ça rend la performance imprévisible et dépendante des structures de données de chaque prop et élément d’état. Au meilleur des cas, vous risquez d’introduire des gels de plusieurs secondes dans votre appli, au pire cas de la faire carrément planter.

  • Renvoyer false n’empêche pas vos composants enfants de refaire leurs calculs si leurs données changent.

  • Renvoyer false ne garantit pas que le composant sautera son rendu. React se servira de votre valeur renvoyée comme d’un conseil, mais reste susceptible d’opter pour un recalcul du rendu si ça lui semble par ailleurs justifié.

Remarque

L’optimisation des composants à base de classes avec shouldComponentUpdate est similaire à l’optimisation des fonctions composants avec memo. Les fonctions composants proposent aussi des optimisations plus granulaires avecuseMemo.


UNSAFE_componentWillMount()

Si vous définissez UNSAFE_componentWillMount, React l’appellera immédiatement après le constructor. Cette méthode n’existe plus que pour des raisons historiques et ne devrait pas être utilisée dans du nouveau code. Utilisez plutôt l’une de ces alternatives :

  • Pour initialiser l’état, déclarez un champ d’instance state ou affectez this.state dans le constructor.
  • Si vous avez besoin d’exécuter un effet de bord ou de souscrire un abonnement, déplacez plutôt cette logique dans componentDidMount.

Consultez des exemples de migration des méthodes historiques de cycle de vie.

Paramètres

UNSAFE_componentWillMount ne prend aucun paramètre.

Valeur renvoyée

UNSAFE_componentWillMount ne devrait rien renvoyer.

Limitations

  • UNSAFE_componentWillMount ne sera pas appelée si le composant implémente static getDerivedStateFromProps ou getSnapshotBeforeUpdate.

  • En dépit de son nom, UNSAFE_componentWillMount ne garantit pas que le composant sera effectivement monté si votre appli utilise des fonctionnalités modernes de React telles que Suspense. Si une tentative de rendu suspend (en raison par exemple d’un code de composant enfant qui ne serait pas encore chargé), React jettera l’arborescence en cours et essaiera de reconstruire le composant de zéro lors de la prochaine tentative. C’est pourquoi cette méthode n’est « pas fiable » (“unsafe”, NdT). Tout code qui se base sur le montage (comme la souscription d’un abonnement) devrait être placé dans componentDidMount.

  • UNSAFE_componentWillMount est la seule méthode de cycle de vie qui est exécutée lors d’un rendu côté serveur. Son déclenchement est en pratique identique à celui de constructor, vous devriez donc plutôt utiliser constructor pour ce type de logique.

Remarque

Appeler setState dans UNSAFE_componentWillMount au sein d’un composant à base de classe, afin d’initialiser l’état du composant, est équivalent au passage de cet état comme état initial à useState dans une fonction composant.


UNSAFE_componentWillReceiveProps(nextProps, nextContext)

Si vous définissez UNSAFE_componentWillReceiveProps, React l’appellera lorsque le composant recevra des nouvelles props. Cette méthode n’existe plus que pour des raisons historiques et ne devrait pas être utilisée dans du nouveau code. Utilisez plutôt l’une de ces alternatives :

  • Si vous avez besoin d’exécuter un effet de bord (par exemple charger des données, dérouler une animation ou réinitialiser un abonnement) en réaction à des changements de props, déplacez plutôt cette logique dans componentDidUpdate.
  • Si vous souhaitez ne recalculer certaines données que lorsque certaines props changent, utilisez plutôt un utilitaire de mémoïsation.
  • Si vous essayez de « réinitialiser » tout l’état quand une prop change, envisagez de plutôt faire un composant soit pleinement contrôlé soit pleinement non contrôlé mais avec une clé.
  • Si vous avez besoin « d’ajuster » une partie de l’état quand une prop change, voyez si vous ne pouvez pas plutôt calculer toutes les infos nécessaires à partir des props seules lors du rendu. Si ce n’est pas possible, préférez static getDerivedStateFromProps.

Consultez des exemples de migration des méthodes historiques de cycle de vie.

Paramètres

  • nextProps : les prochaines props que le composant va recevoir de son composant parent. Comparez nextProps à this.props pour déterminer ce qui a changé.
  • nextContext : le prochain contexte que le composant va recevoir de son plus proche fournisseur de contexte. Comparez nextContext à this.context pour déterminer ce qui a changé. N’est disponible que si vous avez par ailleurs spécifié static contextType (approche plus récente) ou static contextTypes (approche dépréciée).

Valeur renvoyée

UNSAFE_componentWillReceiveProps ne devrait rien renvoyer.

Limitations

  • UNSAFE_componentWillReceiveProps ne sera pas appelée si le composant implémente static getDerivedStateFromProps ou getSnapshotBeforeUpdate.

  • En dépit de son nom, UNSAFE_componentWillReceiveProps ne garantit pas que le composant recevra effectivement ces props si votre appli utilise des fonctionnalités modernes de React telles que Suspense. Si une tentative de rendu suspend (en raison par exemple d’un code de composant enfant qui ne serait pas encore chargé), React jettera l’arborescence en cours et essaiera de reconstruire le composant de zéro lors de la prochaine tentative. D’ici là, les props pourraient avoir encore changé. C’est pourquoi cette méthode n’est « pas fiable » (“unsafe”, NdT). Tout code qui ne devrait être exécuté que pour des mises à jour confirmées (comme la réinitialisation d’un abonnement) devrait être placé dans componentDidUpdate.

  • UNSAFE_componentWillReceiveProps n’implique pas que le composant recevra des props différentes de la fois précédente. Vous devez comparer nextProps avec this.props vous-même pour vérifier que quelque chose a changé.

  • React n’appelle pas UNSAFE_componentWillReceiveProps avec les props initiales lors du montage. Il n’appelle cette méthode que si tout ou partie des props du composant vont être mises à jour. Par exemple, un appel à setState ne déclenche généralement pas UNSAFE_componentWillReceiveProps au sein du même composant.

Remarque

Appeler setState dans UNSAFE_componentWillReceiveProps pour « ajuster » l’état au sein d’un composant à base de classe est équivalent à l’appel d’une fonction set fournie par useState lors du rendu dans une fonction composant.


UNSAFE_componentWillUpdate(nextProps, nextState)

Si vous définissez UNSAFE_componentWillUpdate, React l’appellera avant de refaire un rendu avec les nouvelles props et le nouvel état. Cette méthode n’existe plus que pour des raisons historiques et ne devrait pas être utilisée dans du nouveau code. Utilisez plutôt l’une de ces alternatives :

  • Si vous avez besoin d’exécuter un effet de bord (par exemple charger des données, dérouler une animation ou réinitialiser un abonnement) en réaction à des changements de props ou d’état, déplacez plutôt cette logique dans componentDidUpdate.
  • Si vous avez besoin de lire des informations depuis le DOM (par exemple la position de défilement) pour l’utiliser ensuite dans componentDidUpdate, lisez-la plutôt dans getSnapshotBeforeUpdate.

Consultez des exemples de migration des méthodes historiques de cycle de vie.

Paramètres

  • nextProps : les prochaines props de votre composant pour le rendu à venir. Comparez nextProps à this.props pour déterminer ce qui a changé.
  • nextState : le prochain état de votre composant pour le rendu à venir. Comparez nextState à this.state pour déterminer ce qui a changé.

Valeur renvoyée

UNSAFE_componentWillUpdate ne devrait rien renvoyer.

Limitations

  • UNSAFE_componentWillUpdate ne sera pas appelée si shouldComponentUpdate est définie et renvoie false.

  • UNSAFE_componentWillUpdate ne sera pas appelée si le composant implémente static getDerivedStateFromProps ou getSnapshotBeforeUpdate.

  • Il est interdit d’appeler setState (ou toute méthode entraînant un appel à setState, tel que le dispatch d’une action Redux) au sein de componentWillUpdate.

  • En dépit de son nom, UNSAFE_componentWillUpdate ne garantit pas que le composant sera effectivement mis à jour si votre appli utilise des fonctionnalités modernes de React telles que Suspense. Si une tentative de rendu suspend (en raison par exemple d’un code de composant enfant qui ne serait pas encore chargé), React jettera l’arborescence en cours et essaiera de reconstruire le composant de zéro lors de la prochaine tentative. D’ici là, les props ou l’état pourraient avoir encore changé. C’est pourquoi cette méthode n’est « pas fiable » (“unsafe”, NdT). Tout code qui ne devrait être exécuté que pour des mises à jour confirmées (comme la réinitialisation d’un abonnement) devrait être placé dans componentDidUpdate.

  • UNSAFE_componentWillUpdate n’implique pas que le composant recevra des props ou un état différents de la fois précédente. Vous devez comparer vous-même nextProps avec this.props et nextState avec this.state pour vérifier que quelque chose a changé.

  • React n’appellera pas UNSAFE_componentWillUpdate avec les props et état initiaux lors du montage.

Remarque

Il n’y a pas d’équivalent direct à UNSAFE_componentWillUpdate dans les fonctions composants.


static childContextTypes

Dépréciation

Cette API sera retirée d’une future version majeure de React. Utilisez plutôt static contextType.

Vous permet de spécifier quel contexte historique est fourni par ce composant.


static contextTypes

Dépréciation

Cette API sera retirée d’une future version majeure de React. Utilisez plutôt static contextType.

Vous permet de spécifier quel contexte historique est consommé par ce composant.


static contextType

Si vous souhaitez lire this.context dans votre composant à base de classe, vous devez spécifier le contexte que vous souhaitez lire. Le contexte que vous spécifiez comme static contextType doit être une valeur créée auparavant parcreateContext.

class Button extends Component {
static contextType = ThemeContext;

render() {
const theme = this.context;
const className = 'button-' + theme;
return (
<button className={className}>
{this.props.children}
</button>
);
}
}

Remarque

La lecture de this.context dans les composants à base de classes est équivalente à useContext dans les fonctions composants.

Voyez comment migrer.


static defaultProps

Vous pouvez définir static defaultProps pour fournir des valeurs par défaut aux props de la classe. Elles seront utilisées pour les props manquantes ou valant undefined, mais pas pour les props valant null.

Voici par exemple comment définir une prop color qui devrait valoir 'blue' par défaut :

class Button extends Component {
static defaultProps = {
color: 'blue'
};

render() {
return <button className={this.props.color}>Cliquez ici</button>;
}
}

Si la prop color n’est pas fournie ou est à undefined, elle sera mise par défaut à 'blue' :

<>
{/* this.props.color vaudra "blue" */}
<Button />

{/* this.props.color vaudra "blue" */}
<Button color={undefined} />

{/* this.props.color vaudra null */}
<Button color={null} />

{/* this.props.color vaudra "red" */}
<Button color="red" />
</>

Remarque

La définition de defaultProps dans les composants à base de classes est équivalente à l’utilisation de valeurs par défaut dans les fonctions composants.


static propTypes

Vous pouvez définir static propTypes en utilisant le moduleprop-types pour déclarer les types des props acceptées par votre composant. Ces types seront vérifiés lors du rendu en développement uniquement.

import PropTypes from 'prop-types';

class Greeting extends React.Component {
static propTypes = {
name: PropTypes.string
};

render() {
return (
<h1>Salut {this.props.name}</h1>
);
}
}

Remarque

Nous vous conseillons d’utiliser TypeScript plutôt que de vérifier vos types de props à l’exécution.


static getDerivedStateFromError(error)

Si vous définissez static getDerivedStateFromError, React l’appellera lorsqu’un composant descendant lèvera une erreur pendant le rendu. Ça vous permet d’afficher un message d’erreur plutôt que d’aboutir à une UI vide.

Elle est en général utilisée conjointement avec componentDidCatch, qui vous permet par exemple d’envoyer un rapport d’erreur à un service de supervision. Un composant doté de ces méthodes est ce qu’on appelle un périmètre d’erreur.

Voir un exemple.

Paramètres

  • error : l’erreur qui a été levée. En pratique il s’agira généralement d’une instance d’Error, mais ce n’est pas garanti parce que JavaScript autorise un throw de n’importe quelle valeur, y compris des chaînes de caractères et même null.

Valeur renvoyée

static getDerivedStateFromError devrait renvoyer un objet d’état indiquant au composant d’afficher un message d’erreur.

Limitations

  • static getDerivedStateFromError devrait être une fonction pure. Si vous souhaiter exécuter un effet de bord (comme par exemple un signalement à un service de supervision), vous devez aussi implémenter la méthode componentDidCatch.

Remarque

Il n’y a pas encore d’équivalent direct à static getDerivedStateFromError dans les fonctions composants. Si vous souhaitez éviter de créer des composants à base de classes, écrivez un unique composant ErrorBoundary comme ci-dessus et utilisez-le dans toute votre appli. Vous pouvez aussi utiliser le module react-error-boundary qui fait ça (et davantage) pour vous.


static getDerivedStateFromProps(props, state)

Si vous définissez static getDerivedStateFromProps, React l’appellera juste avant d’appeler render, tant au montage initial que lors des mises à jour ultérieures. Elle devrait renvoyer un objet de mise à jour de l’état, ou null pour ne faire aucune mise à jour.

Cette méthode existe pour les rares cas d’usage où l’état dépend de changements de props au fil du temps. Par exemple, le composant Form ci-dessous réinitialise son état email lorsque la prop userID change :

class Form extends Component {
state = {
email: this.props.defaultEmail,
prevUserID: this.props.userID
};

static getDerivedStateFromProps(props, state) {
// Dès que l’utilisateur actif change, réinitialise
// les parties de l’état liées à cet utilisateur.
// Dans cet exemple simple, il s’agit juste de l’e-mail.
if (props.userID !== state.prevUserID) {
return {
prevUserID: props.userID,
email: props.defaultEmail
};
}
return null;
}

// ...
}

Remarquez que cette approche requiert la conservation de la valeur précédente de la prop (comme userID) dans l’état (comme ici prevUserID).

Piège

Dériver ainsi l’état conduit à du code verbeux et rend difficile la compréhension de vos composants. Assurez-vous de bien connaître les alternatives plus simples :

Paramètres

  • props : les prochaines props pour le rendu à venir.
  • state : le prochain état pour le rendu à venir.

Valeur renvoyée

static getDerivedStateFromProps renvoie un objet utilisé pour mettre à jour l’état, ou null pour ne rien mettre à jour.

Limitations

  • Cette méthode est déclenchée à chaque rendu, peu en importe la raison. Ce n’est pas comme UNSAFE_componentWillReceiveProps, qui elle ne serait déclenchée que lorsque le parent entraîne un nouveau rendu, mais pas suite à un setState local.

  • Cette méthode n’a pas accès à l’instance du composant. Si vous le souhaitez, vous pouvez réutiliser du code entre static getDerivedStateFromProps et les autres méthodes de la classe en extrayant des fonctions pures basées sur les props et l’état du composant, que vous placeriez hors de la définition de la classe.

Remarque

L’implémentation de la méthode static getDerivedStateFromProps dans un composant à base de classe est équivalente à l’appel d’une fonction set fournie par useState lors du rendu dans une fonction composant.


Utilisation

Définir un composant à base de classe

Pour définir un composant React sous forme de classe, étendez la classe Component fournie par React et définissez sa méthode render :

import { Component } from 'react';

class Greeting extends Component {
render() {
return <h1>Salut {this.props.name} !</h1>;
}
}

React appellera votre méthode render dès qu’il doit déterminer quoi afficher à l’écran. Vous y renverrez en général du JSX. Votre méthode render devrait être une fonction pure : elle devrait se limiter à calculer le JSX.

Tout comme les fonctions composants, un composant à base de classe peut recevoir des informations via ses props depuis son composant parent. En revanche, la syntaxe de consultation des props est différente. Si par exemple le composant parent fait le rendu de <Greeting name="Clara" />, vous pourrez lire la prop name depuis this.props, en utilisant this.props.name :

import { Component } from 'react';

class Greeting extends Component {
  render() {
    return <h1>Salut {this.props.name} !</h1>;
  }
}

export default function App() {
  return (
    <>
      <Greeting name="Laure" />
      <Greeting name="Marie" />
      <Greeting name="Nina" />
    </>
  );
}

Remarquez que les Hooks (des fonctions dont le nom commence par use, telles que useState) ne sont pas pris en charge par les composants à base de classes.

Piège

Nous vous conseillons de définir vos composants au moyen de fonctions plutôt que de classes. Voyez comment migrer.


Ajouter de l’état à un composant à base de classe

Pour ajouter un état à une classe, affectez un objet à la propriété state. Pour mettre à jour l’état, appelez this.setState.

import { Component } from 'react';

export default class Counter extends Component {
  state = {
    name: 'Clara',
    age: 31,
  };

  handleNameChange = (e) => {
    this.setState({
      name: e.target.value
    });
  }

  handleAgeChange = () => {
    this.setState({
      age: this.state.age + 1
    });
  };

  render() {
    return (
      <>
        <input
          value={this.state.name}
          onChange={this.handleNameChange}
        />
        <button onClick={this.handleAgeChange}>
          Prendre de l’âge
        </button>
        <p>Salut {this.state.name}. Vous avez {this.state.age} ans.</p>
      </>
    );
  }
}

Piège

Nous vous conseillons de définir vos composants au moyen de fonctions plutôt que de classes. Voyez comment migrer.


Ajouter des méthodes de cycle de vie à un composant à base de classe

Il existe plusieurs méthodes spéciales que vous pouvez définir sur votre classe.

Si vous définissez la méthode componentDidMount, React l’appellera quand votre composant aura été ajouté au DOM (monté). React appellera componentDidUpdate après que votre composant aura refait son rendu en raison de props ou d’un état modifiés. React appellera componentWillUnmount juste avant que votre composant ne soit retiré du DOM (démonté).

Si vous implémentez componentDidMount, vous aurez généralement besoin d’implémenter ces trois méthodes de cycle de vie pour éviter les bugs. Si par exemple componentDidMount lit un état ou des props, vous devrez également implémenter componentDidUpdate pour en gérer les évolutions, ainsi que componentWillUnmount pour nettoyer toute mise en place effectuée dans componentDidMount.

Par exemple, ce composant ChatRoom conserve une connexion au salon de discussion synchronisée avec les props et l’état :

import { Component } from 'react';
import { createConnection } from './chat.js';

export default class ChatRoom extends Component {
  state = {
    serverUrl: 'https://localhost:1234'
  };

  componentDidMount() {
    this.setupConnection();
  }

  componentDidUpdate(prevProps, prevState) {
    if (
      this.props.roomId !== prevProps.roomId ||
      this.state.serverUrl !== prevState.serverUrl
    ) {
      this.destroyConnection();
      this.setupConnection();
    }
  }

  componentWillUnmount() {
    this.destroyConnection();
  }

  setupConnection() {
    this.connection = createConnection(
      this.state.serverUrl,
      this.props.roomId
    );
    this.connection.connect();
  }

  destroyConnection() {
    this.connection.disconnect();
    this.connection = null;
  }

  render() {
    return (
      <>
        <label>
          URL du serveur :{' '}
          <input
            value={this.state.serverUrl}
            onChange={e => {
              this.setState({
                serverUrl: e.target.value
              });
            }}
          />
        </label>
        <h1>Bienvenue dans le salon {this.props.roomId} !</h1>
      </>
    );
  }
}

Remarquez qu’en développement et lorsque le mode strict est actif, React appellera componentDidMount, puis appellera immédiatement componentWillUnmount et rappellera componentDidMount une seconde fois. Ça vous aide à remarquer un oubli d’implémentation de componentWillUnmount, ou un « miroir » insuffisant dans celle-ci de la logique de componentDidMount.

Piège

Nous vous conseillons de définir vos composants au moyen de fonctions plutôt que de classes. Voyez comment migrer.


Capturer les erreurs de rendu avec un périmètre d’erreur

Par défaut, si votre application lève une erreur lors du rendu, React retirera son UI de l’écran. Pour éviter ça, vous pouvez enrober tout ou partie de votre UI dans un périmètre d’erreur. Un périmètre d’erreur est un composant spécial qui vous permet d’afficher une UI de secours plutôt que la partie plantée : un message d’erreur par exemple.

Pour implémenter un composant de périmètre d’erreur, vous devez fournir static getDerivedStateFromError qui vous permet de mettre à jour votre état en réaction à une erreur afin d’afficher un message à l’utilisateur. Vous pouvez aussi, optionnellement, implémenter componentDidCatch pour ajouter de la logique supplémentaire, comme par exemple un signalement de l’erreur à un service de supervision.

class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error) {
// Met à jour l'état pour que le prochain rendu affiche une
// UI de secours.
return { hasError: true };
}

componentDidCatch(error, info) {
// Exemple de "componentStack" :
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logErrorToMyService(error, info.componentStack);
}

render() {
if (this.state.hasError) {
// Vous pouvez afficher n’importe quelle UI de secours
return this.props.fallback;
}

return this.props.children;
}
}

Vous pouvez alors enrober une partie de votre arbre de composants avec le périmètre :

<ErrorBoundary fallback={<p>Ça sent le pâté…</p>}>
<Profile />
</ErrorBoundary>

Si Profile ou un de ses composants descendants lève une erreur, ErrorBoundary « attrapera » cette erreur, affichera une UI de secours avec le message d’erreur fourni, et enverra un signalement de l’erreur de production à votre service de supervision.

Vous n’avez pas besoin d’enrober chaque composant dans son propre périmètre d’erreur. Lorsque vous réfléchissez à la granularité de vos périmètres d’erreurs, pensez aux emplacements logiques pour des messages d’erreurs. Dans une appli de messagerie par exemple, un périmètre d’erreur naturel se situerait autour de la liste des conversations. Il serait également envisageable de placer un périmètre autour de chaque message individuel. En revanche, ça ne servirait à rien d’en placer un autour de chaque avatar.

Remarque

Il n’existe pour le moment pas de moyen d’écrire un périmètre d’erreur sous forme de fonction composant. Ceci dit, vous n’avez pas à écrire votre classe de périmètre d’erreur vous-même. Vous pouvez par exemple utiliser plutôt le module react-error-boundary.


Alternatives

Migrer un composant simple d’une classe vers une fonction

Généralement, vous définirez plutôt vos composants sous forme de fonctions.

Supposons par exemple que vous souhaitiez convertir ce composant à base de classe Greeting en une fonction composant :

import { Component } from 'react';

class Greeting extends Component {
  render() {
    return <h1>Salut {this.props.name} !</h1>;
  }
}

export default function App() {
  return (
    <>
      <Greeting name="Laure" />
      <Greeting name="Marie" />
      <Greeting name="Nina" />
    </>
  );
}

Définissez pour commencer une fonction nommée Greeting. C’est là que vous allez déplacer le corps de votre méthode render :

function Greeting() {
// ... déplacez ici le code de votre méthode `render` ...
}

Plutôt que de lire this.props.name, définissez une prop name au moyen d’une déstructuration dans la signature et lisez-la directement :

function Greeting({ name }) {
return <h1>Salut {name} !</h1>;
}

Voici l’exemple complet :

function Greeting({ name }) {
  return <h1>Salut {name} !</h1>;
}

export default function App() {
  return (
    <>
      <Greeting name="Laure" />
      <Greeting name="Marie" />
      <Greeting name="Nina" />
    </>
  );
}


Migrer un composant avec état d’une classe vers une fonction

Supposons que vous convertissiez ce composant à base de classe Counter vers une fonction :

import { Component } from 'react';

export default class Counter extends Component {
  state = {
    name: 'Clara',
    age: 31,
  };

  handleNameChange = (e) => {
    this.setState({
      name: e.target.value
    });
  }

  handleAgeChange = (e) => {
    this.setState({
      age: this.state.age + 1
    });
  };

  render() {
    return (
      <>
        <input
          value={this.state.name}
          onChange={this.handleNameChange}
        />
        <button onClick={this.handleAgeChange}>
          Prendre de l’âge
        </button>
        <p>Salut {this.state.name}. Vous avez {this.state.age} ans.</p>
      </>
    );
  }
}

Commencez par déclarer une fonction avec les variables d’état nécessaires :

import { useState } from 'react';

function Counter() {
const [name, setName] = useState('Clara');
const [age, setAge] = useState(42);
// ...

Convertissez ensuite les gestionnaires d’événements :

function Counter() {
const [name, setName] = useState('Clara');
const [age, setAge] = useState(42);

function handleNameChange(e) {
setName(e.target.value);
}

function handleAgeChange() {
setAge(age + 1);
}
// ...

Pour finir, remplacez toutes les références qui démarrent par this avec les variables et fonctions définies dans votre composant. Remplacez par exemple this.state.age par age et this.handleNameChange par handleNameChange.

Voici le composant pleinement converti :

import { useState } from 'react';

export default function Counter() {
  const [name, setName] = useState('Clara');
  const [age, setAge] = useState(42);

  function handleNameChange(e) {
    setName(e.target.value);
  }

  function handleAgeChange() {
    setAge(age + 1);
  }

  return (
    <>
      <input
        value={name}
        onChange={handleNameChange}
      />
      <button onClick={handleAgeChange}>
        Prendre de l’âge
      </button>
      <p>Salut {name}. You are {age}.</p>
    </>
  )
}


Migrer un composant doté de méthodes de cycle de vie d’une classe vers une fonction

Supposons que vous convertissiez ce composant à base de classe ChatRoom, doté de méthodes de cycle de vie, vers une fonction :

import { Component } from 'react';
import { createConnection } from './chat.js';

export default class ChatRoom extends Component {
  state = {
    serverUrl: 'https://localhost:1234'
  };

  componentDidMount() {
    this.setupConnection();
  }

  componentDidUpdate(prevProps, prevState) {
    if (
      this.props.roomId !== prevProps.roomId ||
      this.state.serverUrl !== prevState.serverUrl
    ) {
      this.destroyConnection();
      this.setupConnection();
    }
  }

  componentWillUnmount() {
    this.destroyConnection();
  }

  setupConnection() {
    this.connection = createConnection(
      this.state.serverUrl,
      this.props.roomId
    );
    this.connection.connect();
  }

  destroyConnection() {
    this.connection.disconnect();
    this.connection = null;
  }

  render() {
    return (
      <>
        <label>
          URL du serveur :{' '}
          <input
            value={this.state.serverUrl}
            onChange={e => {
              this.setState({
                serverUrl: e.target.value
              });
            }}
          />
        </label>
        <h1>Bienvenue dans le salon {this.props.roomId} !</h1>
      </>
    );
  }
}

Commencez par vérifier que votre componentWillUnmount fait bien l’inverse de votre componentDidMount. Dans l’exemple ci-dessus, c’est bien le cas : elle débranche la connexion établie par componentDidMount. Si cette logique est manquante, commencez par l’ajouter.

Ensuite, vérifiez que votre méthode componentDidUpdate gère les changements des props et états que vous utilisez dans componentDidMount. Dans l’exemple ci-dessus, componentDidMount appelle setupConnection qui lit this.state.serverUrl et this.props.roomId. C’est pourquoi componentDidUpdate vérifie si this.state.serverUrl ou this.props.roomId ont changé, et réinitialise la connexion le cas échéant. Si la logique de votre componentDidUpdate est manquante ou ne gère pas les changements à toutes les parties pertinentes des props et de l’état, corrigez d’abord ça.

Dans l’exemple qui précède, la logique dans les méthodes de cycle de vie connecte le composant à un système extérieur à React (un serveur de discussion). Pour connecter un composant à un système extérieur, décrivez la logique nécessaire dans un Effet unique :

import { useState, useEffect } from 'react';

function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');

useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);

// ...
}

Cet appel à useEffect est équivalent à la logique des méthodes de cycle de vie ci-avant. Si vos méthodes de cycle de vie s’occupent de plusieurs sujets distincts, découpez-les en Effets indépendants. Voici l’exemple complet que vous pouvez manipuler :

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

export default function ChatRoom({ roomId }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
    return () => {
      connection.disconnect();
    };
  }, [roomId, serverUrl]);

  return (
    <>
      <label>
        URL du serveur :{' '}
        <input
          value={serverUrl}
          onChange={e => setServerUrl(e.target.value)}
        />
      </label>
      <h1>Bienvenue dans le salon {roomId} !</h1>
    </>
  );
}

Remarque

Si votre composant ne se synchronise pas avec un système extérieur, alors vous n’avez pas forcément besoin d’un Effet.


Migrer un composant avec un contexte d’une classe vers une fonction

Dans l’exemple qui suit, les composants à base de classes Panel et Button lisent un contexte en utilisant this.context :

import { createContext, Component } from 'react';

const ThemeContext = createContext(null);

class Panel extends Component {
  static contextType = ThemeContext;

  render() {
    const theme = this.context;
    const className = 'panel-' + theme;
    return (
      <section className={className}>
        <h1>{this.props.title}</h1>
        {this.props.children}
      </section>
    );
  }
}

class Button extends Component {
  static contextType = ThemeContext;

  render() {
    const theme = this.context;
    const className = 'button-' + theme;
    return (
      <button className={className}>
        {this.props.children}
      </button>
    );
  }
}

function Form() {
  return (
    <Panel title="Bienvenue">
      <Button>Inscription</Button>
      <Button>Connexion</Button>
    </Panel>
  );
}

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}

Lorsque vous convertissez ça en fonctions composants, remplacez votre utilisation dethis.context par des appels à useContext :

import { createContext, useContext } from 'react';

const ThemeContext = createContext(null);

function Panel({ title, children }) {
  const theme = useContext(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}

function Form() {
  return (
    <Panel title="Bienvenue">
      <Button>Inscription</Button>
      <Button>Connexion</Button>
    </Panel>
  );
}

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}