createEffect¶
1 |
|
Эффекты - это общий способ заставить произвольный код ("побочные эффекты") выполняться при изменении зависимостей, например, для ручной модификации DOM. createEffect
создает новое вычисление, которое запускает заданную функцию в отслеживаемой области видимости, таким образом автоматически отслеживая ее зависимости, и автоматически перевыполняет функцию при обновлении зависимостей. Например:
1 2 3 4 |
|
Эффект будет запускаться всякий раз, когда a
будет менять значение.
Эффект также будет запущен один раз, сразу после его создания, для инициализации DOM до нужного состояния. Это называется фазой "монтирования". Однако мы рекомендуем использовать вместо этого onMount
, который является более явным способом выражения этого.
Обратный вызов эффекта может возвращать значение, которое будет передано в качестве аргумента prev
при следующем вызове эффекта. Это полезно для запоминания значений, которые дорого вычислять. Например:
1 2 3 4 5 6 7 8 9 10 |
|
Эффекты предназначены в основном для побочных эффектов, которые читают, но не пишут в реактивную систему: лучше избегать установки сигналов в эффектах, которые при отсутствии осторожности могут вызвать дополнительный рендеринг или даже бесконечные циклы эффектов. Вместо этого лучше использовать createMemo для вычисления новых значений, зависящих от других реактивных значений, чтобы реактивная система знала, что от чего зависит, и могла оптимизировать соответствующим образом.
Первое выполнение функции эффекта происходит не сразу, а по расписанию после завершения текущей фазы рендеринга (например, после вызова функции, переданной в render, createRoot или runWithOwner). Если необходимо дождаться первого выполнения, используйте queueMicrotask (выполняется до рендеринга DOM браузером) или await Promise.resolve() или setTimeout(..., 0) (выполняется после рендеринга браузером).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Такая задержка первого выполнения полезна, поскольку означает, что эффект, определенный в области видимости компонента, запускается после того, как JSX, возвращаемый компонентом, будет добавлен в DOM. В частности, refs уже будет установлен. Таким образом, эффект можно использовать для ручного управления DOM, вызова библиотек vanilla JS или других побочных эффектов.
Обратите внимание, что первый запуск эффекта все равно выполняется до того, как браузер отрендерит DOM на экран (аналогично useLayoutEffect
в React). Если необходимо дождаться окончания рендеринга (например, для измерения рендеринга), можно использовать await Promise.resolve()
(или Promise.resolve().then(...)
), но следует учитывать, что последующее использование реактивного состояния (например, сигналов) не вызовет повторного запуска эффекта, поскольку отслеживание невозможно после использования await
в асинхронной функции. Таким образом, все зависимости следует использовать до промиса.
Если вы хотите, чтобы эффект выполнялся сразу, даже при первом запуске, используйте createRenderEffect или createComputed.
Очистку побочных эффектов между выполнениями функции эффекта можно производить вызовом onCleanup внутри функции эффекта. Такая функция очистки вызывается как между выполнениями эффекта, так и при его утилизации (например, при размонтировании содержащего компонента). Например:
1 2 3 4 5 6 7 8 9 |
|
Аргументы¶
fn
- Функция для запуска в области отслеживания. Она может возвращать значение, которое будет передано в качестве аргументаprev
при следующем вызове эффекта.value
- Начальное значение эффекта. Это полезно для запоминания значений, которые дорого вычислять.