Эффекты: createEffect, onMount, onCleanup
Эффект — это код, который не строит разметку, а делает что-то «снаружи»: пишет в localStorage, меняет заголовок вкладки, запускает таймер. Solid выполняет эффект после отрисовки и повторяет его, когда меняются сигналы, которые он прочитал.
createEffect
// src/components/Counter.jsx
import { createSignal, createEffect } from 'solid-js';
export default function Counter() {
const [count, setCount] = createSignal(0);
createEffect(() => {
document.title = `Выполнено: ${count()}`;
});
return <button onClick={() => setCount(count() + 1)}>Отметить</button>;
}Заголовок вкладки браузера меняется при каждом нажатии. Список зависимостей, как в useEffect React, не нужен: Solid сам видит, что эффект прочитал count().
Сохранение задач
Эффект удобно использовать, чтобы сохранять список задач между перезагрузками:
// src/App.jsx
import { createSignal, createEffect } from 'solid-js';
export default function App() {
const saved = JSON.parse(localStorage.getItem('todos') ?? '[]');
const [todos, setTodos] = createSignal(saved);
createEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos()));
});
const add = () => setTodos([...todos(), { id: Date.now(), title: 'Задача', done: false }]);
return <button onClick={add}>Добавить ({todos().length})</button>;
}После нескольких нажатий обновите страницу — число на кнопке сохранится.
onMount
onMount выполняется один раз, когда разметка компонента уже вставлена в страницу:
// src/components/Clock.jsx
import { createSignal, onMount, onCleanup } from 'solid-js';
export default function Clock() {
const [time, setTime] = createSignal(new Date().toLocaleTimeString());
onMount(() => {
const timer = setInterval(() => setTime(new Date().toLocaleTimeString()), 1000);
onCleanup(() => clearInterval(timer));
});
return <p>Сейчас {time()}</p>;
}Время на странице обновляется каждую секунду.
onCleanup
onCleanup регистрирует функцию, которая выполнится, когда компонент удаляется со страницы или эффект запускается заново. В примере выше она останавливает таймер, иначе тот продолжал бы работать после удаления Clock.
| Функция | Когда выполняется |
|---|---|
createEffect(fn) | После отрисовки и после каждого изменения прочитанных сигналов |
onMount(fn) | Один раз после вставки в страницу |
onCleanup(fn) | При удалении компонента или перед повтором эффекта |
Частая ошибка
Менять в эффекте тот же сигнал, который он читает:
// src/components/Counter.jsx
import { createSignal, createEffect } from 'solid-js';
export default function Counter() {
const [count, setCount] = createSignal(0);
// Неправильно: эффект запускает сам себя снова и снова
createEffect(() => setCount(count() + 1));
return <p>{count()}</p>;
}Эффект зацикливается. Если значение вычисляется из других сигналов, используйте производную функцию или createMemo, а эффекты оставьте для работы с внешним миром.