Store adalah wadah reaktif untuk objek dan array: kamu membacanya seperti objek biasa (toko.buku[1].stok), tapi tiap propertinya dilacak sendiri-sendiri. createStore dari "solid-js/store" membuatnya, dan perubahannya lewat setter yang menyebut jalur ke bagian yang berubah. Bayangin buku stok Toko Buku Kak Nadia, satu baris per buku, dan tiap kartu di rak mengintip satu baris itu saja. Bumi Manusia terjual, Kak Nadia mengganti satu angka di baris Bumi Manusia, dan cuma kartu Bumi Manusia yang ikut berubah. Kalau semua data disimpan di satu signal, tiap perubahan berarti menulis ulang seluruh buku stok di halaman baru.
🧪 Tebakan cepat: daftar buku dirender dengan
<For>, tiap kartu punya kotak catatan, dan kamu mengetikkadodi kartu Laskar Pelangi. Di pelajaran List Rendering, tombolDiskon Laskar Pelangiyang membuat objek baru menghapus catatan itu. Sekarang datanya disimpan di store dan diskonnya ditulissetToko("buku", 0, "harga", 79000). Catatankadotetap ada atau hilang? Jawabannya ada di bagian "Dibaca per properti".
createStore: objek yang reaktif
Andi, pelanggan tetap Toko Buku Kak Nadia, dan umurnya:
import { createStore } from "solid-js/store"
function App() {
const [state, setState] = createStore({ name: "Andi", age: 25 })
return (
<div>
<p>{state.name} ({state.age})</p>
<button onClick={() => setState("age", a => a + 1)}>+1 Tahun</button>
</div>
)
}
| Kejadian | state.age |
Paragraf |
|---|---|---|
| Halaman dibuka | 25 | Andi (25) |
Klik +1 Tahun |
26 | Andi (26) |
createStorediimpor dari"solid-js/store", bukan dari"solid-js".createStore(objekAwal)mengembalikan pasangan[state, setState], seperticreateSignal.- Isinya dibaca dengan titik, tanpa kurung:
state.name,state.age. Bacaan itu dilacak per properti, sama seperti memanggil signal. setState("age", a => a + 1): argumen pertama nama propertinya, terakhir nilai barunya, atau fungsi yang menerima nilai lama. Ini latihan pertama: paragrafnya persisAndi (25), laluAndi (26)sesudah tombolnya diklik.
Path: menunjuk bagian yang berubah
Data Toko Buku Kak Nadia dalam satu store:
const [toko, setToko] = createStore({
buku: [
{ judul: "Laskar Pelangi", harga: 89000, stok: 4 },
{ judul: "Bumi Manusia", harga: 120000, stok: 2 },
{ judul: "Cantik Itu Luka", harga: 95000, stok: 0 },
],
keranjang: [],
})
Argumen setter dibaca dari kiri ke kanan seperti alamat: properti buku, elemen ke-1, properti stok, lalu nilainya. Diuji di Solid 1.9:
| Panggilan | Hasilnya |
|---|---|
setToko("buku", 1, "stok", s => s - 1) |
stok Bumi Manusia 2 jadi 1 |
setToko("buku", 0, "harga", 79000) |
harga Laskar Pelangi jadi 79000 |
setToko("buku", b => b.stok === 0, "stok", 5) |
fungsi memilih elemen: semua buku yang habis jadi stok 5 |
setToko("buku", 0, { stok: 9 }) |
objek digabung: stok jadi 9, judul dan harga tetap |
setToko("keranjang", k => [...k, "Laskar Pelangi"]) |
keranjang bertambah satu |
Dibaca per properti
Rak Toko Buku Kak Nadia dengan store, kotak catatan di tiap kartu:
import { For } from "solid-js"
import { createStore } from "solid-js/store"
function App() {
const [toko, setToko] = createStore({
buku: [
{ judul: "Laskar Pelangi", harga: 89000, stok: 4 },
{ judul: "Bumi Manusia", harga: 120000, stok: 2 },
{ judul: "Cantik Itu Luka", harga: 95000, stok: 0 },
],
})
const beli = (i) => setToko("buku", i, "stok", s => s - 1)
const diskon = () => setToko("buku", 0, "harga", 79000)
return (
<div>
<button onClick={diskon}>Diskon Laskar Pelangi</button>
<For each={toko.buku}>
{(b, i) => {
console.log("baris dibuat:", b.judul)
return (
<div class="kartu">
<h3>{b.judul}</h3>
<p>Rp{b.harga}</p>
<p>Stok: {b.stok}</p>
<input placeholder="catatan" />
<button onClick={() => beli(i())} disabled={b.stok === 0}>Beli 1</button>
</div>
)
}}
</For>
</div>
)
}
Versi signal-nya menyimpan array yang sama di createSignal, dan mengubahnya dengan objek baru: setBuku(list => list.map((b, j) => (j === i ? { ...b, stok: b.stok - 1 } : b))). Ketik kado di catatan Laskar Pelangi, lalu klik. Diuji di Solid 1.9:
| Klik | createSignal, objek baru |
createStore, path |
|---|---|---|
Beli 1 di Bumi Manusia |
baris dibuat: Bumi Manusia, seluruh kartunya dibuat ulang |
1 teks diganti: Stok: 2 jadi Stok: 1 |
Diskon Laskar Pelangi |
kartu Laskar Pelangi dibuat ulang, catatan kado hilang |
1 teks diganti: Rp89000 jadi Rp79000, catatan kado tetap |
Dengan store, catatan kado tetap. Itu jawaban tebakannya. Setter store gak membuat objek baru. Dia mengganti satu properti di objek yang sama, jadi <For> melihat item yang sama dan gak menyentuh barisnya. Yang jalan cuma bacaan b.harga, satu-satunya yang membaca properti itu. Tiap properti punya pembacanya sendiri: mengubah stok gak menjalankan bacaan harga, dan sebaliknya.
Daftar di dalam store
Array di dalam store juga dilacak, termasuk panjangnya:
const [state, setState] = createStore({
todos: ["Belajar Solid", "Buat proyek"],
input: "",
})
<p>Total: {state.todos.length} todos</p>
<ul>
<For each={state.todos}>{(todo) => <li>{todo}</li>}</For>
</ul>
Paragrafnya Total: 2 todos, dan <ul> berisi dua <li>. Jumlahnya dibaca dari state.todos.length, bukan ditulis angka 2, jadi ikut berubah saat todo bertambah. Ini latihan kedua. state.todos.map(todo => <li>{todo}</li>) juga lolos, tapi <For> yang membuat baris cuma untuk item baru.
Store atau signal?
createSignaluntuk satu nilai: jumlah di keranjang, isi kotak cari, tema.createStoreuntuk objek bersarang dan daftar objek yang bagian-bagiannya berubah sendiri-sendiri: data buku, profil pengguna, isi keranjang.
Keuntungan store: tiap properti dilacak sendiri, jadi perubahan satu properti cuma menjalankan bacaan properti itu.
⚠️ Jebakan yang sering ketemu
- Mengubah store langsung.
toko.buku[0].stok = 3gak mengubah apa pun: store cuma bisa diubah lewat setter-nya. Di mode development, console menulisCannot mutate a Store directly. Cara menulis perubahan seperti objek biasa ada di pelajaran berikutnya,produce. - Memanggil store seperti signal.
state().nameberhenti denganTypeError: state is not a function. Store dibaca dengan titik:state.name. - Destructuring.
const { age } = statemembaca sekali, sama seperti props, dan paragrafnya macet di 25. Bacastate.agelangsung di JSX. - Teks yang gak persis. Latihan pertama membandingkan seluruh paragraf:
Andi (25), dengan spasi sebelum kurung. Latihan kedua mencariTotal: 2di paragraf dan paling sedikit 2<li>di dalam<ul>.
TL;DR: const [state, setState] = createStore({ name: "Andi", age: 25 }) dari "solid-js/store". Dibaca dengan titik tanpa kurung (state.age), dilacak per properti. Diubah lewat setter dengan jalur: setState("age", a => a + 1), setToko("buku", 1, "stok", s => s - 1); fungsi di tengah jalur memilih elemen, objek di akhir digabung. Karena objeknya tetap sama, <For> gak membuat ulang baris, dan cuma bacaan properti yang berubah yang jalan: catatan di kotak input tetap ada. Pakai signal untuk satu nilai, store untuk objek bersarang dan daftar. Store gak bisa diubah langsung: toko.buku[0].stok = 3 gak berpengaruh.