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.