Pourquoi les fragments dans React 16 sont-ils meilleurs que les divs de conteneurs?

165

Dans React 16.2, un support amélioré pour Fragmentsa été ajouté. Plus d'informations peuvent être trouvées sur le blog de React ici.

Nous connaissons tous le code suivant:

render() {
  return (
    // Extraneous div element :(
    <div>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </div>
  );
}

Oui, nous avons besoin d'un conteneur div, mais ce n'est pas si grave.

Dans React 16.2, nous pouvons le faire pour éviter le conteneur div environnant:

render() {
  return (
    <Fragment>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </Fragment>
  );
}

Dans les deux cas, nous avons toujours besoin d'un élément conteneur entourant les éléments internes.

Ma question est, pourquoi est-il Fragmentpréférable d' utiliser un ? Cela aide-t-il à la performance? Si oui, pourquoi? J'adorerais un aperçu.

Max Millington
la source
2
Je le trouve vraiment utile pour le style flexbox lors de la création d'enfants de premier niveau pour un parent
willwoo
32
Le problème avec divest que vous ne voulez pas toujours un élément wrapper. Les éléments wrapper ont une signification et vous avez généralement besoin de styles supplémentaires pour que cette signification soit supprimée. <Fragment>est juste du sucre syntaxique qui n'est pas rendu. Il y a des situations où la création d'un wrapper est très difficile, par exemple en SVG où <div>ne peut pas être utilisé et <group>n'est pas toujours ce que vous voulez.
Sulthan du

Réponses:

305
  1. C'est un peu plus rapide et utilise moins de mémoire (pas besoin de créer un nœud DOM supplémentaire). Cela n'a un réel avantage que sur les arbres très grands et / ou profonds, mais les performances des applications souffrent souvent de la mort par mille coupes. C'est une coupe de moins.
  2. Certains mécanismes CSS comme Flexbox et CSS Grid ont une relation parent-enfant spéciale, et l'ajout de divs au milieu rend difficile le maintien de la mise en page souhaitée lors de l'extraction des composants logiques.
  3. L'inspecteur DOM est moins encombré. :-)

Vous pouvez trouver les descriptions de certains autres cas d'utilisation dans ce problème React: Ajouter une API de fragment pour permettre le retour de plusieurs composants à partir du rendu

Dan Abramov
la source
24
4. La rédaction de listes de définitions <dt><dd>devient beaucoup plus facile. Le retour d'éléments appariés était auparavant gênant Fragments.
Sonson123
Les fragments fonctionnent-ils en natif de réaction? J'ai essayé import Fragment from 'react'. Mais ce n'est pas défini dans RN.
binchik
3
Car number 2, les tables ont été le plus gros problème pour nous. La structure nécessaire de table>tr>td(éventuellement avec theadet similaire) a créé du code React gênant.
Matsemann
2
@binchik a essayé import {Fragment} from 'react'? c'est une exportation nommée.
Soska
1
Le numéro 3 est le plus important!
Zach Smith
28

Ajoutant à toutes les réponses ci - dessus il y a un autre avantage: la lisibilité du code , des Fragmentsupports composant une forme de sucre syntaxique, <>. Ainsi, le code de votre question peut être écrit plus facilement comme:

render() {
  return (
    <>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </>
  );
}

Selon la documentation ,

Dans React, cela désuète un <React.Fragment/>élément, comme dans l'exemple de la section précédente. (Les frameworks non-React qui utilisent JSX peuvent se compiler en quelque chose de différent.)

Sans encombrement, non?

Notez que vous devez toujours utiliser <Fragment> syntaxe si vous devez fournir keyau fragment.

Danois
la source
Cette syntaxe plus courte n'est actuellement pas encore prise en charge dans create-react-app. Référez-vous: reactjs.org/docs/fragments.html#short-syntax
codingsplash
2
@codingsplash CRA 2.0 l'a maintenant.
Rencontrez Zaveri
1
Je ne supporte pas ce morceau de sucre syntaxique, il semble involontaire et ne transmet guère de sens inhérent. Beaucoup préfèrent<Fragment>
ESR
3
@ESR personnellement, j'aime ça. Pense-y de cette façon. Les enfants ne sont enveloppés de rien, tout comme il n'y a rien dans le <>. Invisible.
user3614030
6
  • Ajout de fonctionnalités impossibles auparavant avec JSX
  • Meilleur balisage sémantique jsx. Les éléments wrapper sont utilisés en cas de besoin et non parce qu'ils y sont forcés.
  • Moins de balisage global dom (performances de rendu accrues et moins de surcharge de mémoire)

C'est aussi simple que lorsque vous n'avez pas besoin d'un élément wrapper, vous n'êtes pas obligé d'en utiliser un. Avoir moins d'éléments est génial, mais je pense que le plus grand avantage est de pouvoir rendre des éléments en jsx qui n'étaient pas possibles auparavant et d'ajouter une meilleure signification sémantique aux éléments wrapper car ils sont maintenant optionnels.

Ce n'était pas possible avant:

 <select>
    {this.renderOptions()}
 </select>

En regardant ce qui suit dans React 15, vous ne pouvez pas dire si l'élément wrapper est nécessaire ou non:

<span>
  <h1>Hello</h1>
  {this.getContent()}
</span>
pllee
la source
2

Selon la documentation de reactjs.org, les besoins les plus importants de la <Fragment> </Fragment>place de div sont d'éviter de casser la sémantique HTML. Lorsque nous utilisons des div au lieu de<Fragment> </Fragment> nous cassons la sémantique HTML.

Pour en savoir plus sur la sémantique html. s'il vous plaît cliquer et il y a aussi des cas où si vous utilisez des div au lieu de fragments, ce sera du html invalide, par exemple regardez ce code:

class Columns extends React.Component {
  render() {
    return (
      <div>
        <td>Hello</td>
        <td>World</td>
      </div>
    );
  }
}

<table>
      <tr>
        <div>
          <td>Hello</td>
          <td>World</td>
        </div>
      </tr>
 </table>

Les fragments résolvent ce problème.

Seeta Ram Yadav
la source
1
  1. En utilisant <React.Fragment>...</React.Fragment>, nous pouvons ajouter une balise parent à nos éléments JSX sans ajouter un nœud supplémentaire au DOM.
  2. vous pouvez remplacer les balises div supplémentaires par React.Fragment
  3. écrire React.Fragment à chaque fois est trop long pour vous. React.Fragment a une syntaxe abrégée que vous pouvez utiliser. C'est<>...</>.
Hemant
la source