Children Helper — SolidJS

children() helper menyelesaikan dan melacak children secara reactive. Masalah Di Solid, props.children bisa berupa function, array, atau single element. Akses…

Di Solid, props.children bukan isi yang sudah jadi. Dia getter: setiap kali dibaca, Solid membuat anak-anaknya dari awal, menjalankan lagi komponen di dalamnya, dan membuat elemen DOM baru. Helper children(() => props.children) membacanya sekali, lalu menyimpan hasilnya supaya bisa dibaca berkali-kali. Bayangin Kak Nadia memesan isi rak ke penerbit. Kalau setiap kali dia bertanya "isinya apa?" penerbit mencetak satu set buku baru, gudangnya cepat penuh buku yang gak pernah dipajang. children() itu menerima kirimannya sekali, lalu menghitung dan memajang dari kardus yang sama.

🧪 Tebakan cepat: komponen Rak membaca props.children dua kali: sekali untuk menghitung jumlah buku, sekali untuk menampilkannya. Di dalamnya ada dua KartuBuku, dan masing-masing mencetak KartuBuku jalan ke console. Berapa baris yang tercetak? Jawabannya ada di bagian "props.children adalah getter".

props.children adalah getter

function KartuBuku(props) {
  console.log("KartuBuku jalan:", props.judul)
  return <div class="kartu">{props.judul}</div>
}

function Rak(props) {
  return (
    <section class="rak">
      <p>Isi rak: {props.children.length} buku</p>
      <div class="isi">{props.children}</div>
    </section>
  )
}

function App() {
  return (
    <Rak>
      <KartuBuku judul="Laskar Pelangi" />
      <KartuBuku judul="Bumi Manusia" />
    </Rak>
  )
}

Diuji di Solid 1.9.17, console-nya:

KartuBuku jalan: Laskar Pelangi
KartuBuku jalan: Bumi Manusia
KartuBuku jalan: Laskar Pelangi
KartuBuku jalan: Bumi Manusia

Empat baris, untuk dua kartu. Itu jawaban tebakannya. Halamannya benar, Isi rak: 2 buku dan dua kartu, tapi satu set kartu dibuat cuma untuk dihitung lalu dibuang. Compiler Solid mengubah isi <Rak>...</Rak> jadi getter children, jadi props.children.length membuat satu set, dan {props.children} membuat set kedua.

children(): resolve sekali, baca berkali-kali

import { children } from "solid-js"

function Rak(props) {
  const kartu = children(() => props.children)
  return (
    <section class="rak">
      <p>Isi rak: {kartu.toArray().length} buku</p>
      <div class="isi">{kartu()}</div>
    </section>
  )
}

Sekarang console-nya cuma dua baris, satu per kartu.

Bentuk latihan pelajaran ini:

import { children } from "solid-js"

function Wrapper(props) {
  const resolved = children(() => props.children)

  return <div class="wrapper">{resolved()}</div>
}

function App() {
  return (
    <Wrapper>
      <p>Konten child</p>
    </Wrapper>
  )
}

Mengolah children: kenapa harus di-resolve dulu

Rak mau menandai setiap kartu dengan kelas di-rak:

function Rak(props) {
  const kartu = children(() => props.children)
  createEffect(() => {
    kartu.toArray().forEach((el) => el.classList.add("di-rak"))
  })
  return <section class="rak">{kartu()}</section>
}

Diuji di Solid 1.9.17: dua kartu di halaman jadi class="kartu di-rak". Kalau efeknya menulis props.children.forEach(...), bacaan itu membuat set kartu baru, dan kelasnya mendarat di kartu yang gak pernah tampil. Kartu di halaman tetap class="kartu". Itu maksud "meresolve lazy evaluation": props.children baru dibuat saat dibaca, dan children() mengubahnya jadi elemen DOM nyata yang bisa kamu hitung, ulangi, dan olah.

Kalau komponenmu cuma menaruh {props.children} sekali di JSX, helper ini gak perlu. Pakai saat kamu membaca anak-anaknya lebih dari sekali, atau mau memeriksa dan mengolahnya.

⚠️ Jebakan yang sering ketemu

TL;DR: props.children di Solid adalah getter: tiap bacaan membuat anak-anaknya dari awal, jadi membacanya dua kali menjalankan komponen di dalamnya dua kali (empat baris KartuBuku jalan untuk dua kartu). const resolved = children(() => props.children), dipanggil sekali di badan komponen, me-resolve-nya jadi elemen nyata: resolved() untuk menampilkan, resolved.toArray() untuk menghitung atau mengolah, dan semuanya elemen yang sama dengan yang tampil. Latihannya: <div class="wrapper">{resolved()}</div> di Wrapper, dipakai App sebagai <Wrapper><p>Konten child</p></Wrapper>.

Yang akan kamu pelajari