Stores: createStore
A store is a reactive object or array in which every field is tracked separately. If the done flag of one task changes, only that flag updates, not the whole list. For a task list a store is more convenient than a signal holding an array.
Creating a store
createStore is imported from solid-js/store and, like a signal, returns a pair: the store itself and a setter function.
// src/components/TodoApp.jsx
import { For } from 'solid-js';
import { createStore } from 'solid-js/store';
export default function TodoApp() {
const [todos, setTodos] = createStore([
{ id: 1, title: 'Buy milk', done: false },
{ id: 2, title: 'Call Oleg', done: true },
]);
return (
<ul>
<For each={todos}>{(todo) => <li>{todo.title}</li>}</For>
</ul>
);
}Render <TodoApp /> in src/App.jsx — the page shows a list of two tasks. Unlike a signal, a store is read without parentheses: todos, todos[0].title.
Changing by path
The setter takes a path to a field and the new value:
// src/components/TodoApp.jsx
const add = (title) => {
setTodos(todos.length, { id: Date.now(), title, done: false });
};
const toggle = (id) => {
setTodos((todo) => todo.id === id, 'done', (done) => !done);
};add writes the new task to the position after the last one. In toggle the first argument picks the task with the right id, the second is the field, and the third computes the new value from the old one.
Wiring it into the markup
// src/components/TodoApp.jsx
<ul>
<For each={todos}>
{(todo) => (
<li classList={{ done: todo.done }} onClick={() => toggle(todo.id)}>
{todo.title}
</li>
)}
</For>
</ul>
<button onClick={() => add('New task')}>Add</button>Clicking a task toggles the done class, and the button adds an item. Only the changed li is updated.
produce
If it is easier to change data "in place", like a regular array, use produce:
// src/components/TodoApp.jsx
import { createStore, produce } from 'solid-js/store';
const remove = (id) => {
setTodos(produce((list) => {
const i = list.findIndex((t) => t.id === id);
if (i !== -1) list.splice(i, 1);
}));
};Inside produce you can call push, splice and assign fields. Solid turns these actions into fine-grained updates.
Ways to update
| Task | Code |
|---|---|
| Replace a field | setTodos(0, 'title', 'Buy bread') |
| Append | setTodos(todos.length, newTodo) |
| Change by condition | setTodos((t) => t.done, 'title', 'Done') |
| Change like a plain array | setTodos(produce((list) => ...)) |
Common mistake
Changing the store directly:
// src/components/TodoApp.jsx
// Wrong: direct assignment
todos[0].done = true;
todos.push({ id: 3, title: 'New', done: false });A store is read-only: such changes do not work, and in development mode Solid prints a warning. Make every change through setTodos.