Basic reactivity

createEffect

Edit this page
import { createEffect } from "solid-js"
function createEffect<T>(
compute: () => T,
apply?: (value: T, prev: T | undefined) => (() => void) | void,
initialValue?: T
): void

Effects 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, and Errored boundaries 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.


Arguments

NameTypeDescription
compute() => TA function that runs in a tracking scope, reads reactive values, and returns a value passed to apply.
apply(value: T, prev: T | undefined) => (() => void) | voidAn optional function that receives the computed value and the previous value, and performs side effects. Can return a cleanup function.
initialValueTAn optional initial value for prev on the first run of apply.

  • 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.
Report an issue with this page