Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Хранилища: 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.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.