Encodera

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

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

Оглавление

Производные значения и createMemo

Производное значение — это то, что вычисляется из других данных: количество невыполненных задач, отфильтрованный список, полное имя из имени и фамилии. Хранить его в отдельном сигнале не нужно, достаточно описать, как его получить.

Производная функция

Самый простой способ — обычная стрелочная функция, которая читает сигналы:

// src/components/Counter.jsx
import { createSignal } from 'solid-js';
 
export default function Counter() {
  const [count, setCount] = createSignal(0);
  const doubled = () => count() * 2;
 
  return (
    <div>
      <p>Задач: {count()}, в два раза больше: {doubled()}</p>
      <button onClick={() => setCount(count() + 1)}>Добавить</button>
    </div>
  );
}

При нажатии оба числа обновляются. doubled — функция, поэтому её, как и сигнал, вызывают: doubled(). Вызов внутри JSX читает count(), и Solid отслеживает эту зависимость.

createMemo

Производная функция выполняется каждый раз, когда её вызывают. Если вычисление тяжёлое или результат используется во многих местах, его кешируют через createMemo:

// src/components/TodoStats.jsx
import { createSignal, createMemo } from 'solid-js';
 
export default function TodoStats() {
  const [todos, setTodos] = createSignal([
    { id: 1, title: 'Купить молоко', done: true },
    { id: 2, title: 'Позвонить Олегу', done: false },
  ]);
 
  const left = createMemo(() => todos().filter((t) => !t.done).length);
 
  const add = () => {
    setTodos([...todos(), { id: Date.now(), title: 'Новая задача', done: false }]);
  };
 
  return (
    <div>
      <p>Осталось: {left()}</p>
      <p>Всего: {todos().length}</p>
      <button onClick={add}>Добавить</button>
    </div>
  );
}

На странице «Осталось: 1» и «Всего: 2»; каждое нажатие увеличивает оба числа. createMemo пересчитывает фильтр только при изменении todos, а между изменениями отдаёт сохранённый результат.

Что выбрать

СпособКогда подходит
const x = () => ...Простое вычисление, одно-два места использования
createMemo(() => ...)Тяжёлое вычисление или много читателей

Начинайте с функции. Переходите на createMemo, когда видите, что одно и то же считается много раз.

Memo тоже возвращает функцию

Результат createMemo читается вызовом, как сигнал: left(). Его можно передавать в пропсы и использовать внутри других memo — зависимости выстроятся в цепочку автоматически.

Частая ошибка

Дублировать производное значение в отдельном сигнале и обновлять его вручную:

// src/components/TodoStats.jsx
import { createSignal, createEffect } from 'solid-js';
 
export default function TodoStats() {
  const [todos, setTodos] = createSignal([]);
  // Лишнее: второй сигнал и эффект для синхронизации
  const [total, setTotal] = createSignal(0);
  createEffect(() => setTotal(todos().length));
 
  return <p>Всего: {total()}</p>;
}

Такой код сложнее и может показать устаревшее значение. Достаточно const total = () => todos().length.

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

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