React : bien comprendre les keys

Pourquoi est-il important d’attribuer une key aux éléments d’une liste dans React ?

Concept-clé

Les keys portent bien leur nom car c’est bel et bien un concept-clé dans React.

La key (clé) est un attribut spécial qu’on va ajouter à chaque élément d’une liste. Imaginons le code suivant :

<ul>
{myPosts.map(({post}) => (
    <li key={post.slug}><a href={post.url}>{post.title}</a></li>
))}
</ul>

Source

L’erreur classique

Warning: Each child in an array or iterator should have a unique « key »

Qui ne l’a pas déjà rencontré ? Attention cependant aux solutions naïves pour la résoudre.

Les solutions à éviter

Les solutions qui vont suivre sont dangereuses car elles enlèvent le warning et donnent l’illusion de la victoire !

randomize

La console nous sort un gros warning. Si on ne creuse pas assez la notion, on va se dire osef et potentiellement dériver.

J’ai déjà vu passer sur Internet ce qui suit :

<li key={randomize()}>... etc

Pas très malin ! Le randomize() va provoquer un re-rendu du composant entier systématiquement.

Appliquée partout, cette « technique » risque de vous coûter cher !

C’est un anti-modèle pour l’algorithme de React mais on va y revenir.

Index du tableau

Un conseil, faites pas trop les malins avec ça non plus XD.

L’idée, plutôt moyenne ici voire médiocre, est d’utiliser l’index dans le tableau en tant que key , donc 0,1,2,3,4…n, qui correspondent aux n itérations :

{myData.map((data, index) =>
  <MyComponent {...data} key={index} />
)}

Vous pénétrez dans une zone à risques. Si un ou plusieurs éléments sont supprimés ou ajoutés dynamiquement, ou pire, si vous vous mettez à empiler des tableaux, React risque de s’emmêler les pinceaux.

Que sont les keys ?

React utilise les keys pour identifier chaque élément qui constitue la liste.

Mais pourquoi a-t-il besoin d’identifier ces éléments ? Eh bien parce qu’ainsi il peut grosso modo mieux repérer si un élément de la liste est supprimé, modifié ou ajouté.

De cette façon, il optimise ses manipulation du DOM lors du rendu.

Une bonne pratique

Le mot « bonne pratique » est jeté alors restons méfiant. Un réflexe qu’il faut avoir comme le pschitt-pschitt pour les mains en période de grippe.

Mais tout de même, on peut dire que la key est un identifiant, alors considérez ça en tant que tel.

Perceval en est lui-même étonné !

En reprenant un exemple déjà cité :

<ul>
{myPosts.map(({post}) => (
    <li key={post.id}><a href={post.url}>{post.title}</a></li>
))}
</ul>

j’utilise key={post.id}, je pourrais très bien faire key={post.slug} si j’avais accès au slug de mon post ce qui est très fortement probable. L’ ID a 100% de chance d’être unique et si le système est pas trop débile le slug aussi.

Par opposition, une date, surtout au format Y-m-d, faut forgetter.

Optimiser les manipulation ? Quoi ?

Plus haut, j’emploie l’expression pour essayer de vulgariser ce que fait React avec les keys. Cela présente l’avantage de donner une certaine image et en même temps ça manque de précision et surtout cela veut tout et rien dire à la fois.

Quand vous savez pas trop, dites « ça optimise la perf » et vous brillerez dans les diners en société.

Plus sérieusement, disons que React passe son temps à comparer deux jeux de clés. En fonction des différences entre les anciennes et les nouvelles clés, il pourra soit créer, soit mettre à jour, soit supprimer des éléments de la liste.

Source

C’est la raison pour laquelle les clés doivent être précises et stables. Sans cela, React se comporte comme s’il fallait tout recréer.

Pas de zèle

Si certaines solutions pour fixer le warning s’avèrent naïves voire dangereuses, d’autres sont inutiles.

Ainsi ce qui suit n’est pas une erreur mais n’aura aucun sens :

render() {
    return (
        <MyComponent key="theGreatEscape" />
   );
}

car React n’en fera rien dans sa recherche de différences avec son algorithme de comparaison.

Pas de mal à générer des clés via une librairie mais prenez garde à ce que ces clés soient statiques !

Conclusion

Oui il faut impérativement corriger l’erreur « Warning: Each child in an array or iterator should have a unique key » sous peine de brouiller les échos radars de React.

Les clés sont au cœur du réacteur, explorer la notion permet d’approfondir nettement sa connaissance du langage.