createEffect
Edit this pageIn Solid 2.0, createEffect uses a split model with two functions: a compute function (tracking phase) and an apply function (side-effect phase). The single-callback form is no longer supported — use createTrackedEffect if you need it.
import { createEffect } from "solid-js"
function createEffect<T>( compute: () => T, apply?: (value: T, prev: T | undefined) => (() => void) | void, initialValue?: T): voidEffects are a general way to make arbitrary code ("side effects") run whenever dependencies change, e.g., to modify the DOM manually.
The compute function runs in a tracking scope — it reads reactive values and returns a result. The apply function receives the computed value and the previous value (prev). On the first run, prev is undefined unless you provide an initialValue. The apply function can optionally return a cleanup function that runs before the next execution or when the effect is disposed.
const [count, setCount] = createSignal(0)
createEffect( () => count(), // compute: track dependencies, return value (value, prev) => { // apply: perform side effect with value and previous value console.log("count =", value, "prev =", prev) return () => { // optional cleanup console.log("cleaning up for count", value) } })Why split?
Splitting tracking from side effects means Solid can run all compute phases before any apply phases. This:
- Gives a clear dependency picture before side effects execute
- Enables async,
Loading, andErroredboundaries to work correctly - Prevents accidental feedback loops from signal writes in tracked scope
Compute-only effects
If you only need tracking (no side effect), you can omit the apply function:
createEffect(() => { // This runs in a tracking scope // Useful for registering dependencies trackDependency(someSignal())})Cleanup
The apply function can return a cleanup function. This cleanup runs:
- Before the next execution of the apply function
- When the effect is disposed (e.g., the containing component unmounts)
createEffect( () => eventName(), (event) => { const callback = (e) => console.log(e) ref.addEventListener(event, callback) return () => ref.removeEventListener(event, callback) // cleanup })Execution timing
The first execution of the effect is not immediate; it's scheduled to run after the current rendering phase. If you need to wait for the DOM to be ready, use onSettled.
Writing to signals inside effects warns in dev. Effects are for side effects (DOM updates, logging, external syncing) — not for deriving state. Use createMemo or derived signals instead. If you must write a signal from within a reactive scope, use the { pureWrite: true } option on the signal.
Arguments
| Name | Type | Description |
|---|---|---|
| compute | () => T | A function that runs in a tracking scope, reads reactive values, and returns a value passed to apply. |
| apply | (value: T, prev: T | undefined) => (() => void) | void | An optional function that receives the computed value and the previous value, and performs side effects. Can return a cleanup function. |
| initialValue | T | An optional initial value for prev on the first run of apply. |
Related
createTrackedEffect— Single-callback form for effects that need the older pattern.onSettled— Runs once after the component's initial render is complete.onCleanup— Registers cleanup within a reactive computation.