
Le guide des re-render en React JS
React TypescriptIntroduction
React est une bibliothèque JavaScript populaire utilisée pour la construction d’interfaces utilisateur. L’un des avantages clés de React est sa capacité à mettre à jour de manière efficace l’interface utilisateur en réponse à des changements d’état. Cependant, il peut être parfois difficile de comprendre exactement quand et comment un composant est re-rendu. Dans ce tutoriel, nous allons examiner de plus près comment React gère les re-render des composants.
🎨 Qu’est-ce qu’un re-render ?
Lorsque l’on parle de performances de React, il y a deux étapes majeures dont nous devons nous soucier :
- Le rendu initial : il se produit lorsqu’un composant apparaît pour la première fois à l’écran.
- Le re-render : deuxième rendu et tout rendu consécutif d’un composant qui est déjà affiché à l’écran.
Le re-rendu se produit lorsque React doit mettre à jour l’application avec de nouvelles données. Habituellement, cela se produit à la suite d’une interaction d’un utilisateur avec l’application ou de certaines données externes via une demande asynchrone ou un modèle d’abonnement.
🧐 Comment se déclenche le re-render ?
Il y a quatre raisons pour lesquelles un composant se re-render de lui-même : les changements d’état, les re-rendus parent (ou enfants), les changements de Context
et les changements des Hooks
.
Il existe également un grand mythe : les rendus se produisent lorsque les Props du composant changent. En soi, ce n’est pas vrai !
🔋 Le changement d’état
Lorsque l’état d’un composant change, il se re-render de lui-même. Habituellement, cela se produit soit dans un callback
, soit dans le hook useEffect
.
Les changements d’état sont la source principale de tous les re-rendus.
import { FC, useState } from "react";
export const MyComponent: FC = () => {
// when setLabel function is called, the MyComponent re-render itself
const [label, setLabel] = useState("");
return <div>{label}</div>;
};
🧔🏻♂️ Le parent se re-render
Un composant s’affichera à nouveau si son parent s’affiche à nouveau. Ou, si nous regardons cela dans la direction opposée : lorsqu’un composant se re-render, il re-render également tous ses enfants.
Le re-render va toujours vers le bas de l’arborescence : le re-rendu d’un enfant ne déclenche pas le re-rendu d’un parent.
import { FC } from "react";
export const Parent: FC = () => {
// if Parent component is re-rendered, the Child component will also be re-renderer
return <Child />;
};
🔍 Utilisation des Contexts
Lorsque la valeur stockée dans un Context
React change, tous les composants qui utilisent ce même Context
seront re-rendus, même s’ils n’utilisent pas directement la partie modifiée des données. Ces re-rendus ne peuvent pas être empêchés avec la mémorisation directement, mais il existe quelques solutions de contournement qui peuvent le simuler.
// context/drawer-context.tsx
import { createContext, PropsWithChildren, useState } from "react";
interface AppContextInterface {
isDrawerOpen: boolean;
}
const AppContext = createContext<AppContextInterface>({
isDrawerOpen: false,
});
export const AppContextProvider: PropsWithChildren = ({ children }) => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
return (
<AppContext.Provider value={{ isDrawerOpen }}>
{children}
</AppContext.Provider>
);
};
export default AppContext;
// components/Component1.tsx
import { FC, useContext, useState } from "react";
export const Component1: FC = () => {
// when setIsDrawerOpen from context is called, the Component1 re-render itself
const { setIsDrawerOpen } = useContext(AppContext);
function onClickHandler(): void {
setIsDrawerOpen(true);
}
return <button onClick={onClickHandler}>Open Drawer</button>;
};
🔗 Changement d’état d’un custom hook
Tout ce qui se passe à l’intérieur d’un Hook
affecte le composant qui l’utilise. Les mêmes règles concernant les changements de Context
et d’état s’appliquent ici :
-
Le changement d’état à l’intérieur d’un
Hook
déclenchera un nouveau rendu inévitable du composant hôte. -
Si le
Hook
utilise les changements de valeur deContext
, il déclenchera un re-rendu inévitable du composant hôte.
// hooks/use-form-input.ts
import { useState, FormEvent } from "react";
export function useFormInput(initialValue: string) {
const [value, setValue] = useState(initialValue);
function handleChange(event: FormEvent<HTMLInputElement>) {
setValue(event.target.value);
}
return {
value,
onChange: handleChange,
};
}
//components/Component2.tsx
import { Fragment, FC } from "react";
import { useFormInput } from "../../hooks/use-form-input.ts";
export const Component2: FC = () => {
// when handleChange from custom hook is called, the Component2 re-render itself
const firstNameProps = useFormInput("Mary");
return (
<Fragment>
<label>FirstName</label>
<input {...firstNameProps} />
</Fragment>
);
};
🤥 Le faux mythe : le changement des Props
Peu importe que les Props du composant changent ou non lorsqu’il s’agit de re-render des composants non mémorisés.
Pour que les Props changent, elles doivent être mis à jour par le composant parent. Cela signifie que le parent devra effectuer un nouveau rendu, ce qui déclenchera un nouveau rendu du composant enfant, quels que soient ses Props.
Ce n’est que lorsque des techniques de mémorisation sont utilisées comme React.memo
ou useMemo
que le changement des Props aura de l’importance.
import { FC } from "react";
export const Parent: FC = () => {
let value = "my value";
useEffect(() => {
value = "my value2";
}, []);
// if value changed, the Parent and Child will not be re-rendered.
// if Parent component is re-rendered, the Child component will also be re-renderer
return <Child value={value} />;
};