Comment utiliser les clés React pour éviter les conflits de composants

L’approche React peut être assez compliquée, et vous pouvez rencontrer des comportements inattendus ou même des bugs subtils. Se débarrasser de tels bugs peut être assez difficile si vous n’êtes pas familier avec leur cause.


VIDÉO MUO DU JOUR

FAIRE DÉFILER POUR CONTINUER AVEC LE CONTENU

Un bug particulier survient lorsque vous rendez conditionnellement le même composant avec des propriétés différentes. Explorez ce bug en détail et découvrez comment utiliser les clés React pour le résoudre.


Les composants React ne sont pas toujours indépendants

Sa syntaxe simple est l’une des principales raisons pour lesquelles vous devriez apprendre React. Mais, malgré de nombreux avantages, le framework n’est pas exempt de bugs.

Le bug que vous allez découvrir ici se produit lorsque vous effectuez un rendu conditionnel du même composant, mais que vous lui transmettez des props différents.

Dans des cas comme celui-ci, React supposera que les deux composants sont les mêmes, et ne prendra donc pas la peine de rendre le second composant. Par conséquent, tout état que vous définissez dans le premier composant persistera entre les rendus.

Prenons l’exemple suivant. Tout d’abord, vous avez le composant suivant Compteur composant :

 import { useState, useEffect } from "react"

export function Counter({name}) {
  const (count, setCount) = useState(0)

  return(
    <div>
      <div>{name}</div>
      <button onClick={() => setCount(c => c - 1)}> - </button>
      <br />
      <button onClick={() => setCount(c => c + 1)}> + </button>
    </div>
  )
}

Ce Comptoir Le composant accepte un nom du parent via la déstructuration d’objet, qui est une façon d’utiliser les props dans React. Ensuite, il rend le nom dans un <div&gt ;. Il renvoie également deux boutons : l’un pour décrémenter le compte et l’autre pour l’incrémenter.

Gardez à l’esprit qu’il n’y a rien d’anormal dans le code ci-dessus. Le problème vient du bloc de code suivant (le composant App), qui utilise le compteur :

 import { useState } from "react"
import { Counter } from "./Counter"

export default function App() {
  const (isKingsley, setIsKingsley) = useState(true)

  return(
    <div>
      { isKingsley ? <Counter name="Kingsley" /> : <Counter name="Sally" /> }
      <br />
      <button onClick={() => setIsKingsley(k => !k)}> Swap </button>
    </div>
  )
}

Par défaut, le code ci-dessus rend le compteur nommé Kingsley. Si vous incrémentez le compteur à cinq et que vous cliquez sur le bouton Échanger le deuxième compteur nommé Sally sera rendu.

Mais le problème est que le compteur ne se remettra pas à son état par défaut de zéro après que vous les ayez échangés.

Ce bug se produit parce que les deux états rendent les mêmes éléments dans le même ordre. React ne sait pas que le compteur « Kingsley » est différent du compteur « Sally ». La seule différence se trouve dans l’élément nom mais, malheureusement, React ne l’utilise pas pour différencier les éléments.

Vous pouvez contourner ce problème de deux manières. La première est de modifier votre DOM et de rendre les deux arbres différents. Pour cela, il faut comprendre ce qu’est le DOM. Par exemple, vous pouvez placer le premier compteur à l’intérieur d’un objet <div&gt ; et le second à l’intérieur d’un élément <section&gt ; élément :

 import { useState } from "react"
import { Counter } from "./Counter"

export default function App() {
  const (isKingsley, setIsKingsley) = useState(true)

  return (
    <div>
      { isKingsley ?
        (<div>
          <Counter name="Kingsley" />
        </div>)
        :
        (<section>
          <Counter name="Sally" />
        </section>)
      }
      <br />
      <button onClick={() => setIsKingsley(k => !k)}> Swap </button>
    </div>
  )
}

Si vous incrémentez le compteur « Kingsley » et cliquez sur ÉchangerEncore une fois, cela se produit parce que la structure des deux arbres DOM est différente.

Lorsque le estKingsley variable est vraila structure sera div &gt ; div &gt ; Comptoir (un div contenant un div, contenant un compteur). Lorsque vous permutez l’état du compteur à l’aide du bouton, la structure devient div &gt ; section &gt ; Comptoir. En raison de cette divergence, React rendra automatiquement un nouveau compteur avec un état réinitialisé.

Il se peut que vous ne souhaitiez pas toujours modifier la structure de votre balisage de cette manière. La deuxième façon de résoudre ce bogue évite d’avoir à modifier le balisage.

Utilisation de clés pour le rendu d’un nouveau composant

Les clés permettent à React de différencier les éléments au cours du processus de rendu. Ainsi, si vous avez deux éléments qui sont exactement les mêmes, et que vous voulez signaler à React que l’un est différent de l’autre, vous devez définir un attribut de clé unique sur chaque élément.

Ajoutez une clé à chaque compteur, comme ceci :

 import { useState } from "react"
import { Counter } from "./Counter"

export default function App() {
  const (isKingsley, setIsKingsley) = useState(true)

  return(
    <div>
      { isKingsley ?
        <Counter key="Kingsley" name="Kingsley" /> :
        <Counter key="Sally" name="Sally" />
      }
      <br />
      <button onClick={() => setIsKingsley(k => !k)}> Swap </button>
    </div>
  )
}

Désormais, lorsque vous incrémentez le compteur « Kingsley » et que vous cliquez sur ÉchangerReact rend un nouveau compteur et remet l’état à zéro.

Vous devriez également utiliser des clés lorsque vous rendez un tableau d’éléments du même type, car React ne connaîtra pas la différence entre chaque élément.

 export default function App() {
  const names = ("Kingsley", "John", "Ahmed")

  return(
    <div>
      { names.map((name, index) => {
        return <Counter key={index} name={name} />
      })}
    </div>
  )
}

Lorsque vous attribuez des clés, React associe un compteur distinct à chaque élément. De cette façon, il peut refléter tous les changements que vous apportez au tableau.

Un autre cas d’utilisation avancé des clés

Vous pouvez également utiliser des clés pour associer un élément à un autre élément. Par exemple, vous pouvez associer un élément d’entrée à différents éléments en fonction de la valeur d’une variable d’état.

Pour faire une démonstration, modifiez le composant App :

 import { useState } from "react"

export default function App() {
  const (isKingsley, setIsKingsley) = useState(true)

  return(
    <div>
      { isKingsley ? <div>Kingsley's Score</div> : <div>Sally's score</div> }
      <input key={ isKingsley? "Kingsley" : "Sally" } type="number"/>
      <br />
      <button onClick={() => setIsKingsley(k => !k)}> Swap </button>
    </div>
  )
}

Désormais, chaque fois que vous passez d’un composant à l’autre, le composant <div&gt ; Pour les éléments Kingsley et Sally, vous changez automatiquement l’attribut key de votre entrée entre « Kingsley » et « Sally ». Cela obligera React à re-rendre complètement l’élément input à chaque clic sur le bouton.

Plus de conseils pour optimiser les applications React

L’optimisation du code est essentielle pour créer une expérience utilisateur agréable dans votre application web ou mobile. Connaître les différentes techniques d’optimisation peut vous aider à tirer le meilleur parti de vos applications React.

La meilleure partie est que vous pouvez appliquer la plupart de ces techniques d’optimisation avec les applications React Native également.

Laisser un commentaire