Reactivity

createEffect

Creates a reactive effect with separate compute and effect phases.

  • compute(prev) runs reactively — put all reactive reads here. The returned value is passed to effect and is also the new "previous" value for the next run.
  • effect(next, prev?) runs imperatively (untracked) after the queue flushes. Put DOM writes / fetch / logging / subscriptions here. It may return a cleanup function which runs before the next effect or on disposal.

Reactive reads inside effect will not re-trigger this effect — that's intentional. If you need a single-phase tracked effect, use createTrackedEffect (with the tradeoffs noted there).

Pass an EffectBundle ({ effect, error }) instead of a plain function to intercept errors thrown from the compute or effect phases.

createEffect<T>(compute, effectFn | { effect, error }, options?: EffectOptions);

Deprecated: createEffect(compute) (single argument) is no longer supported. Pass a separate effect function as the second argument: createEffect(compute, effect). See MISSING_EFFECT_FN.

  • For a side effect that reacts to changes, split the work: createEffect(() => signal(), value => doWork(value)).
  • For a derived value, use createMemo(() => signal()).
  • For a one-shot side effect at construction time, just call the function.

Import

import { createEffect } from "solid-js";

Type signature

function createEffect<T>(
compute: ComputeFunction<undefined | NoInfer<T>, T>,
effectFn: EffectFunction<NoInfer<T>, T> | EffectBundle<NoInfer<T>, T>,
options?: EffectOptions
): void;
function createEffect<T>(
compute: ComputeFunction<undefined | NoInfer<T>, T>
): never;

Parameters

compute

A function that receives its previous value and returns a new value used to react on a computation

effectFn

A function that receives the new value and is used to perform side effects (return a cleanup function), or an EffectBundle with effect and error handlers

options

EffectOptions -- name, defer, schedule


Examples

const [count, setCount] = createSignal(0);
createEffect(
() => count(), // compute: tracks `count`
(value) => console.log(value) // effect: side effect
);
setCount(1); // logs 1 after the next flush
createEffect(
() => userId(),
(id) => {
const ctrl = new AbortController();
fetch(`/users/${id}`, { signal: ctrl.signal });
return () => ctrl.abort(); // cleanup before next run / disposal
}
);

ComputeFunction

type ComputeFunction<Prev, Next extends Prev = Prev> = (
v: Prev
) => PromiseLike<Next> | AsyncIterable<Next> | Next;

EffectBundle

type EffectBundle<Prev, Next extends Prev = Prev> = {
effect: EffectFunction<Prev, Next>;
error: (err: unknown, cleanup: () => void) => void;
};

effect

  • Type: EffectFunction&lt;Prev, Next&gt;

error

  • Type: (err: unknown, cleanup: () => void) => void

EffectFunction

type EffectFunction<Prev, Next extends Prev = Prev> = (
v: Next,
p?: Prev
) => (() => void) | void;

EffectOptions

Options for effect primitives that support deferring/scheduling their initial run (createEffect, createRenderEffect, createReaction).

interface EffectOptions extends BaseEffectOptions {
defer?: boolean;
schedule?: boolean;
sync?: boolean;
}

defer

  • Type: boolean

When true, defers the initial effect execution until the next change

schedule

  • Type: boolean

When true, enqueues the initial effect callback through the effect queue instead of running it synchronously at creation. Lets the initial run participate in transitions -- if any source throws NotReadyError during the compute phase, the callback is held until the transition settles.

Primarily for render effects that need transition-aware initial mounts (e.g. The root insert() in render()).

sync

  • Type: boolean

Advanced. When true, asserts the compute function returns synchronous values only (never PromiseLike / AsyncIterable). Skips the async-shape probe in recompute for a small fixed-cost win per run. Intended for compiler emissions (_$effect) and library code that provably returns sync values. Returning a Promise or async iterable from a sync: true effect is undefined behavior — the value will be stored as-is and never awaited.

Last updated: 7/4/26, 6:21 PMEdit this pageReport an issue with this page