Stores Solid — SolidJS

Stores adalah nested reactive state — seperti signal tapi untuk objek dan array. createStore import { createStore } from "solid-js/store" function App() {…

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 mengetik kado di kartu Laskar Pelangi. Di pelajaran List Rendering, tombol Diskon Laskar Pelangi yang membuat objek baru menghapus catatan itu. Sekarang datanya disimpan di store dan diskonnya ditulis setToko("buku", 0, "harga", 79000). Catatan kado tetap 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)

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?

Keuntungan store: tiap properti dilacak sendiri, jadi perubahan satu properti cuma menjalankan bacaan properti itu.

⚠️ Jebakan yang sering ketemu

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.

Yang akan kamu pelajari