Reactivity

createMemo

Creates a readonly derived reactive memoized signal.

const value = createMemo<T>(compute, options?: MemoOptions<T>);

Import

import { createMemo } from "solid-js";

Type signature

function createMemo<T>(
compute: ComputeFunction<undefined | NoInfer<T>, T>,
options?: MemoOptions<T>
): SourceAccessor<T>;

Parameters

compute

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

options

MemoOptions -- id, name, equals, unobserved, lazy


Examples

const [first, setFirst] = createSignal("Ada");
const [last, setLast] = createSignal("Lovelace");
const fullName = createMemo(() => `${first()} ${last()}`);
fullName(); // "Ada Lovelace"
// Async memo — reads surface as pending inside <Loading>
const user = createMemo(async () => {
const res = await fetch(`/users/${id()}`);
return res.json();
});

isEqual

function isEqual<T>(a: T, b: T): boolean;

MemoOptions

Options for read-only memos created with createMemo. Also used in combination with SignalOptions for writable memos (createSignal(fn) / createOptimistic(fn)).

interface MemoOptions<T> {
id?: string;
name?: string;
transparent?: boolean;
equals?: false | ((prev: T, next: T) => boolean);
unobserved?: () => void;
lazy?: boolean;
sync?: boolean;
}

id

  • Type: string

Stable identifier for the owner hierarchy

name

  • Type: string

Debug name (dev mode only)

transparent

  • Type: boolean

When true, the owner is invisible to the ID scheme -- inherits parent ID and doesn't consume a childCount slot

equals

  • Type: false | ((prev: T, next: T) => boolean)

Custom equality function, or false to always notify subscribers. Defaults to reference equality (isEqual). Pass a comparator (e.g. (a, b) => a.id === b.id) for value-based equality, or false to notify on every recompute regardless of equality.

unobserved

  • Type: () => void

Callback invoked when the computed loses all subscribers

lazy

  • Type: boolean

When true, defers the initial computation until the value is first read, and opts the memo into autodisposal — once it has no remaining subscribers it is torn down and recomputed from scratch on the next read. Use it for compute-on-demand values that should not retain state across idle periods. Non-lazy owned memos live for their owner's lifetime and never autodispose.

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 (_$memo) and library code that provably returns sync values. Returning a Promise or async iterable from a sync: true memo is undefined behavior — the value will be stored as-is and never awaited.

SignalOptions

Options for plain signals created with createSignal(value) or createOptimistic(value).

interface SignalOptions<T> {
name?: string;
equals?: false | ((prev: T, next: T) => boolean);
ownedWrite?: boolean;
unobserved?: () => void;
}

name

  • Type: string

Debug name (dev mode only)

equals

  • Type: false | ((prev: T, next: T) => boolean)

Custom equality function, or false to always notify subscribers. Defaults to reference equality (isEqual). Pass a comparator (e.g. (a, b) => a.id === b.id) for value-based equality, or false to notify on every write regardless of equality.

ownedWrite

  • Type: boolean

Suppress dev-mode warnings when writing inside an owned scope

unobserved

  • Type: () => void

Callback invoked when the signal loses all subscribers

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