Хранилища: createStore
Хранилище (store) — это реактивный объект или массив, у которого отслеживается каждое поле по отдельности. Если у одной задачи поменялась отметка done, обновится только эта отметка, а не весь список. Для списка задач хранилище удобнее, чем сигнал с массивом.
Создание хранилища
createStore импортируется из solid-js/store и, как сигнал, возвращает пару: само хранилище и функцию изменения.
// 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: 'Купить молоко', done: false },
{ id: 2, title: 'Позвонить Олегу', done: true },
]);
return (
<ul>
<For each={todos}>{(todo) => <li>{todo.title}</li>}</For>
</ul>
);
}Выведите <TodoApp /> в src/App.jsx — на странице список из двух задач. В отличие от сигнала, хранилище читают без скобок: todos, todos[0].title.
Изменение по пути
Функция изменения принимает путь к полю и новое значение:
// 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 записывает новую задачу в позицию за последней. В toggle первый аргумент выбирает задачу с нужным id, второй — поле, третий вычисляет новое значение из старого.
Подключение к разметке
// 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('Новая задача')}>Добавить</button>Щелчок по задаче переключает класс done, кнопка добавляет пункт. Перерисовывается только изменившийся li.
produce
Если удобнее менять данные «на месте», как обычный массив, используйте 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);
}));
};Внутри produce можно вызывать push, splice и присваивать поля. Solid сам превратит эти действия в точечные обновления.
Способы изменения
| Задача | Код |
|---|---|
| Заменить поле | setTodos(0, 'title', 'Купить хлеб') |
| Добавить в конец | setTodos(todos.length, newTodo) |
| Изменить по условию | setTodos((t) => t.done, 'title', 'Готово') |
| Изменить как обычный массив | setTodos(produce((list) => ...)) |
Частая ошибка
Менять хранилище напрямую:
// src/components/TodoApp.jsx
// Неправильно: прямое присваивание
todos[0].done = true;
todos.push({ id: 3, title: 'Новая', done: false });Хранилище доступно только для чтения: такие изменения не сработают, а в режиме разработки Solid выведет предупреждение. Все изменения делайте через setTodos.