Signals — SolidJS

Signals adalah primitif reaktivitas utama di Solid — getter/setter pair. createSignal import { createSignal } from "solid-js" function Counter() { const…

Signal adalah wadah nilai reaktif paling kecil di Solid. createSignal(0) memberimu dua hal: getter untuk membaca nilainya dan setter untuk menggantinya. Tiap tempat yang membaca getter di JSX dicatat Solid, dan saat setter menulis nilai baru, cuma tempat-tempat itu yang diperbarui. Bayangin papan angka keranjang di kasir Toko Buku Kak Nadia, dengan daftar nama di sampingnya. Siapa pun yang melirik angkanya otomatis tercatat di daftar. Saat angkanya diganti, Kak Nadia cuma memberi tahu orang-orang di daftar itu, gak semua orang di toko. Melirik angka itu memanggil getter, jumlah(). Mengganti angka itu setter, setJumlah(...). Daftarnya dicatat Solid sendiri.

🧪 Tebakan cepat: keranjang punya const [jumlah, setJumlah] = createSignal(0) dan paragraf <p>Total: Rp{jumlah * 89000}</p> (tanpa kurung sesudah jumlah). Yang tampil apa: Total: Rp0, Total: RpNaN, atau error? Jawabannya ada di bagian "Getter dipanggil pakai kurung".

createSignal: getter dan setter

import { createSignal } from "solid-js"

function App() {
  const [count, setCount] = createSignal(0)

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>+1</button>
      <p>Count: {count()}</p>
    </div>
  )
}

Itu persis latihan pertama pelajaran ini. Baris import boleh ditulis, editor latihan juga sudah menyediakan createSignal.

Setter: nilai atau fungsi updater

Setter bisa menerima nilai baru, atau fungsi yang menghitung nilai baru dari nilai lama (namanya updater):

setJumlah(jumlah() + 1)   // nilai: baca sekarang, tambah 1
setJumlah(j => j + 1)     // updater: Solid memberi nilai lama sebagai j
setJumlah(1)              // nilai tetap: selalu 1

Cuma teks yang membaca yang berubah

Ini keranjang Toko Buku Kak Nadia dengan total harga:

function App() {
  const [jumlah, setJumlah] = createSignal(0)
  console.log("App jalan")

  return (
    <div>
      <h2>Laskar Pelangi · Rp89.000</h2>
      <button onClick={() => setJumlah(j => j + 1)}>+1 Buku</button>
      <p>Keranjang: {jumlah()} buku</p>
      <p>Total: Rp{jumlah() * 89000}</p>
    </div>
  )
}
Kejadian jumlah() Text node yang diganti Console
Halaman dibuka 0 App jalan
Klik +1 Buku 1 0 jadi 1, 0 jadi 89000
Klik lagi 2 1 jadi 2, 89000 jadi 178000

Dua tempat membaca jumlah(), jadi tiap klik mengganti tepat dua text node. Judul buku dan tombolnya gak disentuh, dan App gak jalan lagi.

Getter dipanggil pakai kurung

jumlah (tanpa kurung) adalah fungsinya, bukan angkanya. Fungsi dikali angka hasilnya NaN, jadi Total: Rp{jumlah * 89000} tampil Total: RpNaN, tanpa error. Itu jawaban tebakannya. Angkanya juga gak pernah berubah, karena gak ada pembacaan jumlah() yang bisa diikuti.

Hasil lain dari lupa kurung, diuji di Solid 1.9:

Ditulis Tampil
{jumlah()} 0, lalu ikut berubah
{jumlah} 0, lalu ikut berubah (Solid menerima fungsi di posisi ini, tapi itu kebetulan)
{jumlah + 1} function () { [native code] }1
{`${jumlah} buku`} function () { [native code] } buku
console.log(jumlah) fungsinya, bukan angkanya

Jadi biasakan selalu menulis jumlah(). {count} yang kebetulan tampil itu bukan cara yang benar, dan begitu nilainya dipakai menghitung, hasilnya rusak.

Input yang menulis ke signal

function App() {
  const [name, setName] = createSignal("Dunia")

  return (
    <div>
      <input value={name()} onInput={e => setName(e.target.value)} />
      <h1>Halo, {name()}!</h1>
    </div>
  )
}

Pakai onInput, bukan onChange. Di Solid, onChange memakai event change asli browser, yang baru jalan saat kotaknya ditinggalkan (blur), bukan tiap ketikan seperti di React.

⚠️ Jebakan yang sering ketemu

TL;DR: const [count, setCount] = createSignal(0) membuat signal: count() membaca, setCount(...) menulis. Setter menerima nilai (setCount(count() + 1)) atau updater (setCount(c => c + 1)); nilai tetap seperti setCount(1) berhenti di 1. Signal berubah saat itu juga, dan cuma teks yang membaca getter-nya yang diganti, sedangkan fungsi komponennya gak jalan lagi. Getter selalu dipanggil pakai kurung: tanpa kurung, {jumlah * 89000} tampil NaN. Untuk input, onInput={e => setName(e.target.value)} lalu tampilkan {name()}; onChange di Solid baru jalan saat kotaknya ditinggalkan.

Yang akan kamu pelajari