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 sesudahjumlah). 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>
)
}
createSignal(0)membuat signal dengan nilai awal0, dan mengembalikan array berisi dua fungsi.const [count, setCount]memberi nama keduanya. Kebiasaannya: nama nilainya, laluset+ nama itu, jadicountdansetCount.count()membaca nilainya. Ditulis di dalam<p>, Solid mencatat bahwa teks itu mengikuticount.setCount(c => c + 1)menulis nilai baru. Teks yang mengikuticountlangsung berubah:Count: 0, sekali klikCount: 1, dua kaliCount: 2.
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
- Dua baris pertama sama-sama menambah 1 tiap klik. Signal Solid berubah saat itu juga, jadi
jumlah()yang dibaca sesudah setter sudah nilai baru. Tiga kalisetJumlah(jumlah() + 1)dalam satu klik menambah 3. - Updater (
j => j + 1) paling aman untuk "tambah dari nilai sebelumnya", karena gak perlu membaca getter-nya sendiri. setJumlah(1)menulis angka yang sama tiap klik. Klik pertama jadi 1, klik kedua tetap 1, dan karena nilainya gak berubah, Solid gak memperbarui apa pun. Latihan pertama menekan tombolnya dua kali dan menungguCount: 2, jadi bentuk ini gagal.
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>
)
}
createSignal("Dunia")membuat sapaan awalnyaHalo, Dunia!.onInputjalan tiap kali isi kotak berubah, satu kali per ketikan.e.target.valueadalah isi kotaknya, dansetNamemenyimpannya ke signal.<h1>membacaname(), jadi ikut berubah: ketikBudi, tampilHalo, Budi!. KetikSinta, tampilHalo, Sinta!. Ini latihan kedua.value={name()}membuat isi kotak mengikuti signal juga, misalnya kalau signal-nya diganti dari tempat lain.
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
- Lupa kurung.
{jumlah * 89000}tampilNaN,{jumlah + 1}tampil teks fungsinya. Selalujumlah(). - Setter dengan nilai tetap.
setCount(1)berhenti di 1. Untuk menambah, tulissetCount(c => c + 1)atausetCount(count() + 1). - Variabel biasa.
let count = 0lalucount++gak memberi tahu siapa-siapa, jadi teksnya tetap 0. Nilai yang berubah disimpan di signal. onChangeuntuk mengetik. Dia baru jalan saat kotaknya ditinggalkan. Latihan kedua mengetik ke kotaknya dan langsung membaca judulnya, jadi pakaionInput.
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.