Fragment React memungkinkan sebuah komponen mengembalikan beberapa elemen tanpa membungkusnya dengan <div> tambahan. Tulis <> sebelum elemen pertama dan </> setelah elemen terakhir, dan React menaruh elemen-elemen itu langsung ke dalam induknya, tanpa node sendiri di halaman.
Setiap Greeting mengembalikan sebuah heading dan sebuah paragraf secara berdampingan. Hapus baris <> dan </>, dan pratinjau justru menampilkan error build, karena fungsinya sekarang mencoba mengembalikan dua nilai.
Kenapa komponen butuh satu root
JSX adalah cara yang lebih enak untuk menulis pemanggilan fungsi. <h2>Hi</h2> dikompilasi menjadi kira-kira jsx('h2', { children: 'Hi' }), satu ekspresi. Pernyataan return hanya bisa mengembalikan satu nilai, jadi dua tag bersebelahan tanpa pembungkus sama saja dengan menulis return a b: compiler berhenti dengan "Adjacent JSX elements must be wrapped in an enclosing tag".
Sebelum ada fragment, solusinya adalah <div> pembungkus. Cara itu berhasil, tetapi div adalah elemen sungguhan. Div muncul di DOM, ikut serta dalam layout CSS, dan beberapa induk sama sekali tidak menerimanya sebagai anak. Fragment memenuhi aturan satu root lalu menghilang.
Kamu bisa melihat bahwa fragment tidak menambahkan apa pun. Contoh di bawah merender dua item yang sama lewat fragment dan lewat div, lalu menghitung anak langsung dari setiap container.
Konsol mencetak 2 untuk fragment, yaitu kedua span, dan 1 untuk div, yang membungkus keduanya. Di dalam container flex atau grid, perbedaan itu menentukan apakah span-span itu diatur sebagai item sendiri atau dibungkus menjadi satu.
Sintaks pendek dan komponen Fragment
Ada dua cara menulis fragment, dan keduanya dikompilasi menjadi hal yang sama:
import { Fragment } from 'react';
// Short syntax, no import needed
<>
<dt>React</dt>
<dd>A library for building user interfaces</dd>
</>
// Long form
<Fragment>
<dt>React</dt>
<dd>A library for building user interfaces</dd>
</Fragment>
Pakai <>...</> hampir di mana saja. Gunakan <Fragment> dalam satu kasus: saat fragment butuh key. Sintaks pendek tidak bisa menerima atribut, jadi <key={id}> bukan JSX yang valid. Kamu mungkin juga melihat <React.Fragment> di kode lama; itu komponen yang sama, diakses lewat default import React.
Fragment dengan key di dalam list
Saat kamu merender list dengan map, setiap item butuh key agar React bisa melacaknya di antara render (halaman tentang list dan key menjelaskan alasannya). Jika setiap item adalah sekelompok elemen, bukan satu elemen, key-nya ditaruh di fragment, jadi kamu butuh bentuk panjangnya.
Description list adalah contoh klasiknya: setiap entri adalah sebuah <dt> dan sebuah <dd>, dan <dl> seharusnya berisi keduanya secara langsung.
Klik Reverse, dan pasangan-pasangan itu bertukar tempat sebagai satu kesatuan, karena setiap pasangan punya key sendiri. <div> pembungkus di setiap pasangan juga bisa menerima key, dan valid sebagai HTML di dalam dl, tetapi ia menambahkan level ketiga ke markup yang tidak ditambahkan oleh fragment.
Fragment di dalam tabel
Tabel adalah tempat pembungkus nyasar paling merugikan. Sebuah <tr> mengharapkan sel <td> dan <th> sebagai anak langsungnya. Jika komponen yang mengembalikan beberapa sel membungkusnya dengan <div>, browser memperlakukan div itu sebagai satu sel yang aneh, dan sel-sel di dalamnya tidak lagi sejajar dengan header.
Baris fragment menaruh harganya di bawah Price dan stoknya di bawah Stock. Di baris div, kedua sel terjepit di kolom Price dan kolom Stock kosong. Saat development, React juga mencatat peringatan bahwa <div> tidak boleh menjadi anak dari <tr>; pratinjau berjalan seperti build production, jadi pemeriksaan itu dilewati, dan layout yang rusak itulah yang kamu lihat di sini. Dengan server rendering, kesalahan yang sama juga bisa menyebabkan error hydration, karena parser HTML milik browser memindahkan div yang salah tempat itu.
Aturan yang sama berlaku untuk <ul> dan <ol>, yang seharusnya berisi elemen <li>, dan untuk <select>, yang seharusnya berisi elemen <option>. Setiap kali sebuah komponen mengembalikan bagian-bagian yang harus berada langsung di dalam induk seperti itu, kembalikan fragment.
Fragment atau array
Sebuah komponen juga bisa mengembalikan array berisi elemen, dan React merendernya secara berurutan seperti fragment. Setiap elemen di array yang dikembalikan butuh key sendiri, sama seperti output map, karena React memperlakukan array itu sebagai list:
function Cells() {
return [<td key="price">$4</td>, <td key="stock">In stock</td>];
}
Cara ini berhasil, tetapi lebih ramai: koma di antara elemen, key di setiap elemen, dan kurung siku yang mudah terlewat saat markup-nya bertambah panjang. Pakai fragment untuk sekelompok elemen yang tetap, dan pakai array untuk kegunaan alaminya, yaitu hasil map atas data.
Yang tidak bisa dilakukan fragment
Karena fragment tidak merender elemen apa pun, ia tidak punya tempat untuk menaruh class, style, event handler, atau ref. <Fragment className="row"> tidak melakukan apa pun yang berguna, dan satu-satunya prop yang dibaca React dari fragment adalah key. Saat kamu perlu memberi gaya pada kelompok itu atau mendengarkan klik padanya, kamu memang butuh elemen sungguhan, dan itu tidak masalah: pilih elemen yang valid di posisinya, seperti <tbody> untuk mengelompokkan baris atau <li> untuk menampung item list.
Fragment bisa dipakai di mana saja elemen bisa dipakai, termasuk di dalam conditional rendering: {show && <>...</>} menampilkan atau menyembunyikan seluruh kelompok sekaligus.
Pertanyaan yang sering diajukan
Apa itu Fragment di React?
Fragment adalah pembungkus yang memungkinkan komponen mengembalikan beberapa elemen sebagai satu nilai tanpa menambah node DOM. <><h1 /><p /></> menaruh h1 dan p langsung ke dalam induknya.
Apa perbedaan <> dan <Fragment>?
Keduanya menghasilkan hal yang sama. <>...</> adalah sintaks pendeknya. <Fragment> adalah bentuk panjang yang kamu import dari react, dan hanya bentuk ini yang bisa menerima key, yang kamu butuhkan saat merender fragment di dalam list.
Kenapa memakai Fragment, bukan div?
Div adalah elemen sungguhan. Div bisa merusak layout yang mengharapkan anak langsung (container flex dan grid, ul, table, tr) dan menambah kerumitan di DOM. Fragment tidak menambahkan apa pun.
Bisakah Fragment punya className atau onClick?
Tidak. Fragment tidak merender elemen apa pun, jadi tidak ada tempat untuk menaruh class, style, atau event handler. Satu-satunya prop yang diterimanya adalah key. Jika kamu butuh salah satunya, pakai elemen sungguhan.
Kenapa saya mendapat "Adjacent JSX elements must be wrapped in an enclosing tag"?
Sebuah komponen mengembalikan dua elemen bersebelahan tanpa pembungkus apa pun. JSX dikompilasi menjadi satu ekspresi, jadi bungkus elemen-elemen itu dengan <>...</>.