Limiter les rendus des lignes indépendantes
Objectif : Empêcher une ligne de dépense inchangée de se recalculer lors de la modification d’une autre ligne.
Quand vous supprimez ou modifiez une dépense, la liste peut être recalculée et plusieurs lignes peuvent être rendues de nouveau. Si une ligne inchangée effectue un travail important, ce rendu peut devenir perceptible. Vous allez isoler chaque ligne pour que React puisse éviter ce travail lorsque ses propriétés n’ont pas changé.
Vous avez déjà stabilisé le callback de suppression dans la leçon précédente ; vérifiez que cette optimisation a bien été conservée après profilage. Ici, vous allez l’associer à une ligne mémoïsée, plutôt que d’appliquer React.memo à toute la liste sans distinction.
Isoler une ligne de dépense
React.memo compare les propriétés reçues par un composant à celles de son rendu précédent. Si elles sont identiques, React peut réutiliser le résultat précédent au lieu de rendre ce composant à nouveau. Cette comparaison ne porte pas sur les données cachées dans le composant parent : une nouvelle fonction ou un nouvel objet transmis en propriété peut donc invalider le résultat.
Pour rendre les lignes indépendantes, donnez à chacune les valeurs nécessaires à son affichage et à son action : identifiant, date, description, catégorie, montant et callback de suppression. Les champs utilisés ici reprennent ceux du tableau du projet. La ligne n’a pas besoin de recevoir toute la dépense si cela complique la stabilité de ses propriétés.
import { memo } from "react";
type DepenseLigneProps = {
id: string;
date: string;
description: string;
categorie: string;
montant: number;
supprimerDepense: (id: string) => void;
};
const DepenseLigne = memo(function DepenseLigne({
id,
date,
description,
categorie,
montant,
supprimerDepense,
}: DepenseLigneProps) {
return (
<tr>
<td>{date}</td>
<td>{description}</td>
<td>{categorie}</td>
<td>{montant}</td>
<td>
<button
type="button"
onClick={() => supprimerDepense(id)}
aria-label={`Supprimer ${description}`}
>
Supprimer
</button>
</td>
</tr>
);
});
export default DepenseLigne;Dans le rendu du tableau, remplacez le contenu de chaque ligne par ce composant et passez-lui des valeurs primitives provenant de la dépense. Conservez la clé React sur le composant créé dans la boucle, afin que React associe chaque dépense à la bonne ligne lorsque la liste change.
<tbody>
{depensesFiltrees.map((depense) => (
<DepenseLigne
key={depense.id}
id={depense.id}
date={depense.date}
description={depense.description}
categorie={depense.categorie}
montant={depense.montant}
supprimerDepense={supprimerDepense}
/>
))}
</tbody>Vérifier le bénéfice, pas seulement le code
Reprenez la même interaction et le même jeu de données que dans votre profil de référence : par exemple, supprimez une dépense et observez si les autres lignes rendent encore leur contenu. Avec React DevTools Profiler, comparez les composants rendus et la durée de l’interaction avant et après. Une ligne absente du profil lors d’une mise à jour indique que React a pu réutiliser son rendu, mais le résultat global peut rester identique si le travail évité est négligeable.
La mémoïsation a aussi un coût : comparaison des propriétés, complexité supplémentaire et risque de masquer une mise à jour attendue si le modèle des données est mal conçu. Gardez-la seulement si le profilage montre un gain utile dans les interactions réelles. Sinon, retirez React.memo et conservez le composant le plus simple à maintenir.
À retenir
- React.memo peut éviter le rendu d’une ligne lorsque ses propriétés restent identiques.
- Transmettez à la ligne les propriétés minimales nécessaires, de préférence des valeurs primitives.
- Un callback recréé ou un objet recréé peut invalider la comparaison et annuler l’optimisation.
- Comparez les profils avant et après sur la même interaction ; retirez la mémoïsation si le gain n’est pas mesurable.
La prochaine leçon porte sur la structure native de la page et la hiérarchie de ses titres.