Fragmenty w React

Jakiś czas temu pojawiła się nowa wersja Reacta oznaczona numerkiem 16.2.0. Oprócz poprawek, wprowadza ona nową składnię dla czegoś co nazywane jest przez twórców Fragmentami. I dzisiaj krótko lecz treściwie o tym właśnie.

Na początku był pewien problem…

Wyobraźmy sobie, że nasza przykładowa aplikacja w Reakcie składa się z nagłówka, tekstu i stopki. I teraz chcielibyśmy sobie te elementy wyrenderować do elementu o identyfikatorze #app. Otóż bez dodatkowego elementu „opakowującego” pozostałe, ta sztuka się nie uda. Nie jest to oczywiście problem tylko Reacta, bo z tego co pamiętam już nawet Backbone.js się z tym borykał, ale to temat na zupełnie inną dyskusję. Wyobraźmy więc sobie następującą funkcję render:

render() {
  return (
    <div> {/* konieczny div, którego byśmy nie chcieli */}
      <header>Przykładowa apka</header>
      <p>Przykładowy tekst</p>
      <footer>Taka prosta stopka</footer>
    </div>
  );
}

Może być ona częścią komponentu o nazwie… np. App, następnie chcemy ten komponent wyrenderować do wskazanego przez nas elementu:

ReactDOM.render(<App />, document.querySelector('#app'));

Wszystko fajnie, ale czy możemy się jakoś obejść bez tego nieszczęsnego, zbędnego elementu?

… a potem pojawiło się rozwiązanie!

React w wersji 16, oprócz znaczących zmian pod maską, wprowadził wspomniane w tytule fragmenty. Jest to specjalna notacja tablicowa, z pomocą której możemy pozbyć się dodatkowych elementów opakowujących ciało komponentu. Spójrzmy na poprzedni przykład, uzupełniony o składnię tablicową:

render() {
  return (
    [
      <header key="1">Przykładowa apka</header>,
      <p key="2">Przykładowy tekst</p>,
      <footer key="3">Taka prosta stopka</footer>,
    ];
  );
}

I dzięki temu sposobowi zapisu pozbyliśmy się niepotrzebnego elementu. Jednak nie nazwałbym tej składni czymś wspaniałym. Skoro zwracamy tablicę to należy pamiętać, że każdy element musi posiadać atrybut key i musi być oddzielony przecinkiem. Przy małej ilości elementów nie jest to straszliwy ból, ale wyobraźmy sobie jak to może wyglądać przy większej ilości węzłów.



Nowa składnia fragmentów – czyli da się jeszcze lepiej!

Składnia tablicowa pozwala nam pominąć zbędny element opakowujący, ale nie jest ona zbyt wygodna. Na szczęście od wersji 16.2 Reacta jesteśmy już w stanie zaimportować element Fragment, dzięki któremu składnia praktycznie zostanie niezmieniona w stosunku do pierwszego przykładu, a my pozbędziemy się dodatkowego elementu. Spójrzmy jak to wygląda w praktyce:

import { Fragment } from "react";

...

render() {
  return (
    <Fragment>
      <header>Przykładowa apka</header>
      <p>Przykładowy tekst</p>
      <footer>Taka prosta stopka</footer>
    </Fragment>
  );
}

Znacznie lepiej prawda? Nie różni się to praktycznie niczym innym jak tylko zastąpieniem elementu opakowującego wspomnianym już wielokrotnie fragmentem. Istnieje jeszcze prostsza składnia, która pozwala pominąć słówko Fragment, a wygląda ona w ten sposób:

render() {
  return (
    <>
      <header>Przykładowa apka</header>
      <p>Przykładowy tekst</p>
      <footer>Taka prosta stopka</footer>
    </>
  );
}

Na pierwszy rzut oka to przeoczenie nazwy elementu HTML, ale wygląda całkiem uroczo ^^. Za pomocą „pseudo elementu” <> i </> jesteśmy w stanie uzyskać ten sam rezultat co w przypadku skorzystania z elementu Fragment. Bomba! 🙂

Podsumowanie

Fragmenty w React pozwalają na pominięcie dodatkowego elementu opakowującego ciało komponentu i dzięki banalnej składni z pewnością znajdą swoich fanów. Dzięki nim będziemy w stanie np. wyrzucać kilka komórek tablicy z jednego komponentu, czy też w wygodny sposób renderować elementy znacznika listy definicji (<df>). Elementy listy definicji składają się ze znacznika nazwy terminu <dt> i objaśnienia terminu <dd>. Bez fragmentów składanie takiej listy z podwójnych elementów jest po prostu smutne 😉