React: Les éléments de liste avec une "clé" unique sont re-rendus lorsque l'ordre des éléments change.

Créé le 15 juil. 2018  ·  3Commentaires  ·  Source: facebook/react

Vous souhaitez demander une fonctionnalité ou signaler un bug ?
Bogue

Quel est le comportement actuel ?
Lors du rendu d'une liste d'éléments avec key défini comme propriété unique sur chaque élément d'élément, si l'ordre des éléments change par rapport au rendu précédent, les éléments d'élément dont les index ont changé sont rendus à nouveau (une nouvelle instance est créée) au lieu de re -utilisation d'une instance existante (mappée via une clé).

Par exemple https://codesandbox.io/s/r5p48kzop
Rendu d'une liste boxes avec chaque boîte ayant id , top , left & color accessoires. Tous les 750ms nous mettons à jour les valeurs ( top , left ) pour tous les éléments du tableau boxes .

Lors de la mise à jour, si l'ordre des éléments ne change pas, chaque boîte s'anime à sa nouvelle position. Cependant, si nous décommentons la ligne 31 qui mélange les cases, alors seuls les éléments qui conservent leur position du rendu précédent s'animent vers de nouvelles positions.

Vous pouvez observer ce comportement dans le bac à sable. Avec _shuffle activés, les boîtes sautent parfois vers leurs nouvelles positions tandis qu'avec _shuffle désactivées, elles s'animent toujours.

Si le comportement actuel est un bogue, veuillez fournir les étapes à reproduire et si possible une démo minimale du problème. Collez le lien vers votre exemple JSFiddle (https://jsfiddle.net/Luktwrdm/) ou CodeSandbox (https://codesandbox.io/s/new) ci-dessous :
https://codesandbox.io/s/r5p48kzop

Quel est le comportement attendu ?
Quel que soit l'ordre de boxes tous les éléments de la boîte doivent s'animer à leurs nouvelles positions car ils ont une propriété unique key définie sur eux.

Quelles versions de React, et quel navigateur/OS sont concernés par ce problème ?
Réagissez 16.3.2 & 16.4.1 , Chrome, MacOS.

Commentaire le plus utile

Salut @dhruvparmar372 !

Cela semble être une limitation du DOM. Pour le démontrer, j'ai créé ce JSFiddle qui modifie l'ordre de deux nœuds DOM, puis applique une classe pour déclencher une transition.

Il s'avère que vous pouvez contourner ce problème en déclenchant une redistribution entre la modification de l'ordre et la mise à jour des propriétés de l'animation.

J'ai ajouté un peu de code à votre CodeSandbox pour le rendre visible lorsqu'un composant est recréé par React en modifiant le <Box /> en composant de classe et en créant un identifiant unique dans le constructeur. Comme vous pouvez le voir, l'identifiant restera cohérent : https://codesandbox.io/s/jn42wvl343

En plus de cela, j'ai appliqué la solution de contournement de la redistribution à votre exemple en divisant la mise à jour en deux setState s. Le premier va changer l'ordre, puis on déclenche un reflow, et ensuite on change la position. Cela semble fonctionner correctement dans Chrome, Firefox, Safari et Edge (CodeSandbox ne prend pas en charge IE11, je n'ai donc pas pu tester sur ce navigateur).

Tous les 3 commentaires

Salut @dhruvparmar372 !

Cela semble être une limitation du DOM. Pour le démontrer, j'ai créé ce JSFiddle qui modifie l'ordre de deux nœuds DOM, puis applique une classe pour déclencher une transition.

Il s'avère que vous pouvez contourner ce problème en déclenchant une redistribution entre la modification de l'ordre et la mise à jour des propriétés de l'animation.

J'ai ajouté un peu de code à votre CodeSandbox pour le rendre visible lorsqu'un composant est recréé par React en modifiant le <Box /> en composant de classe et en créant un identifiant unique dans le constructeur. Comme vous pouvez le voir, l'identifiant restera cohérent : https://codesandbox.io/s/jn42wvl343

En plus de cela, j'ai appliqué la solution de contournement de la redistribution à votre exemple en divisant la mise à jour en deux setState s. Le premier va changer l'ordre, puis on déclenche un reflow, et ensuite on change la position. Cela semble fonctionner correctement dans Chrome, Firefox, Safari et Edge (CodeSandbox ne prend pas en charge IE11, je n'ai donc pas pu tester sur ce navigateur).

salut @philipp-spiess merci d'avoir clarifié le problème et les exemples de solution de contournement.

Salut, @philipp-spiess

J'ai le même problème avec la liste de tri 😔
Malheureusement, votre exemple Codesandbox ci-dessus ne fonctionne plus (

Voici un exemple:
https://jsfiddle.net/9odLvbrx/
Il trie les éléments au clic avec une simple transition CSS.
Le problème est que la transition n'apparaît que sur l'élément sélectionné et omet le reste.

Je sais comment contourner le problème (commenté dans le code) mais cela ne fonctionne bien que sur les listes dont la quantité d'articles ne change jamais. Donc, si je veux ajouter ou supprimer un élément, les choses deviennent incroyablement complexes. Comment puis-je utiliser votre solution de surcharge de refusion pour que cela se produise dans mon exemple ?

Merci d'avance! ??

Cette page vous a été utile?
0 / 5 - 0 notes