Perché i frammenti in React 16 sono migliori dei div container?


165

In React 16.2 Fragmentsè stato aggiunto un supporto migliorato per . Maggiori informazioni sono disponibili sul post del blog di React qui.

Conosciamo tutti il ​​seguente codice:

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

Sì, abbiamo bisogno di un div container, ma non è un grosso problema.

In React 16.2, possiamo farlo per evitare il div contenitore circostante:

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

In entrambi i casi, abbiamo ancora bisogno di un elemento contenitore che circonda gli elementi interni.

La mia domanda è: perché usare un Fragmentpreferibile? Aiuta con le prestazioni? Se è così, perché? Mi piacerebbe un po 'di intuizione.


2
Lo trovo davvero utile per lo stile della flexbox quando si creano figli di primo livello per un genitore
willwoo

32
Il problema divè che non si desidera sempre un elemento wrapper. Gli elementi wrapper hanno un significato e di solito sono necessari stili aggiuntivi per rimuovere quel significato. <Fragment>è solo zucchero sintattico che non viene reso. Ci sono situazioni in cui la creazione di un wrapper è molto difficile, ad esempio in SVG dove <div>non può essere utilizzato e <group>non è sempre quello che desideri.
Sulthan,

Risposte:


305
  1. È un po 'più veloce e ha meno utilizzo della memoria (non è necessario creare un nodo DOM aggiuntivo). Questo ha un reale vantaggio solo su alberi molto grandi e / o profondi, ma le prestazioni dell'applicazione spesso subiscono la morte di mille tagli. Questo è un taglio in meno.
  2. Alcuni meccanismi CSS come Flexbox e CSS Grid hanno una relazione genitore-figlio speciale e l'aggiunta di divs nel mezzo rende difficile mantenere il layout desiderato durante l'estrazione di componenti logici.
  3. L'ispettore DOM è meno disordinato. :-)

Puoi trovare le descrizioni di alcuni altri casi d'uso in questo problema di React: Aggiungi API frammento per consentire la restituzione di più componenti dal rendering


24
4. Scrivere elenchi di definizioni <dt><dd>diventa molto più semplice. Restituire elementi accoppiati era prima imbarazzante Fragments.
Sonson123,

I frammenti funzionano in reattivo? Ci ho provato import Fragment from 'react'. Ma non è definito in RN.
Binchik,

3
Perché number 2, i tavoli sono stati effettivamente il problema più grande per noi. La struttura necessaria di table>tr>td(possibilmente con theade simili) ha creato un codice React scomodo.
Matsemann,

2
@binchik provato import {Fragment} from 'react'? è un'esportazione denominata.
Soska,

1
Il numero 3 è il più importante!
Zach Smith,

28

Aggiungendo a tutte le risposte di cui sopra v'è un altro vantaggio: la leggibilità del codice , Fragmentsupporti componenti una forma di zucchero sintattico, <>. Quindi il codice nella tua domanda può essere scritto più facilmente come:

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

Secondo i documenti ,

In React, questo desugars a un <React.Fragment/>elemento, come nell'esempio della sezione precedente. (I framework non React che utilizzano JSX possono essere compilati in modo diverso.)

Senza confusione, vero?

Si noti che è ancora necessario utilizzare la <Fragment>sintassi se è necessario fornire keyal frammento.


Questa sintassi più breve non è attualmente supportata in create-reazioni-app. Fare riferimento: reazionejs.org/docs/fragments.html#short-syntax
codingsplash

2
@codingsplash CRA 2.0 ce l'ha ora.
Incontra Zaveri il

1
Non sopporta questo pezzo di zucchero sintattico, sembra involontario e trasmette poco significato intrinseco. Molto preferisco<Fragment>
ESR,

3
@ESR personalmente mi piace. Pensare in questo modo. I bambini non sono avvolti nel nulla, proprio come non c'è nulla nel <>. Invisibile.
user3614030,

6
  • Aggiunte funzionalità non possibili prima con JSX
  • Migliore markup jsx semantico. Gli elementi wrapper vengono utilizzati quando necessario, non perché sono costretti a farlo.
  • Meno markup dom complessivo (aumento delle prestazioni di rendering e minore sovraccarico di memoria)

Semplice come quando non hai bisogno di un elemento wrapper non sei obbligato a usarne uno. Avere meno elementi è fantastico, ma penso che il più grande vantaggio sia la possibilità di renderizzare elementi in jsx che prima non erano possibili e aggiungere un migliore significato semantico agli elementi wrapper perché ora sono opzionali.

Questo non era possibile prima:

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

Dando un'occhiata a quanto segue in React 15 non è possibile stabilire se l'elemento wrapper è necessario o meno:

<span>
  <h1>Hello</h1>
  {this.getContent()}
</span>

2

Secondo i documenti Reactjs.org, le esigenze più importanti <Fragment> </Fragment>invece di quelle di div sono evitare la rottura della semantica HTML. Quando usiamo div invece di <Fragment> </Fragment>rompere la semantica HTML.

Per saperne di più sulla semantica html. fai clic e inoltre ci sono casi in cui se usi div invece di Fragments sarà html non valido, ad esempio guarda questo codice:

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>

I frammenti risolvono questo problema.


1
  1. Usando <React.Fragment>...</React.Fragment>, possiamo aggiungere un tag genitore ai nostri elementi JSX senza aggiungere un nodo extra al DOM.
  2. puoi sostituire i tag div extra con React.Fragment
  3. scrivere React.Fragment ogni volta che è troppo lungo per te. React.Fragment ha una sintassi abbreviata che puoi usare. È<>...</>.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.