createMemo
Edit this pageThe createMemo function creates a read-only signal that derives its value from other reactive values.
The calculated value is memoized: the calculation runs only when dependencies change, and is reused when the value is read.
When a dependency changes, the calculation re-executes.
If the new result is equal to the previous result (according to the equals option), the memo suppresses downstream updates.
Import
import { createMemo } from "solid-js";Type
function createMemo<T>( fn: (v: T) => T, value?: T, options?: { equals?: false | ((prev: T, next: T) => boolean); name?: string }): () => T;Parameters
fn
- Type:
(v: T) => T - Required: Yes
The function that calculates the memo's value.
It receives the value returned from the previous execution as its argument.
On the first execution, it receives the value parameter (if provided) or undefined.
This function should be pure (it should not modify other reactive values).
value
- Type:
T - Required: No
The initial value passed to fn on its first execution.
options
- Type:
{ equals?: false | ((prev: T, next: T) => boolean); name?: string } - Required: No
An optional configuration object with the following properties:
equals
- Type:
false | ((prev: T, next: T) => boolean) - Required: No
A function that runs after each execution of fn to determine if the memo value has changed.
It receives the previous and the new value.
If it returns true, the values are considered equal and the memo does not trigger downstream updates.
If set to false (instead of a function), the memo triggers updates whenever it re-executes, even if the value is unchanged.
Defaults to a function that compares values using strict equality (===).
name
- Type:
string - Required: No
A debug name for the memo. It is used for identification in debugging tools like the Solid Debugger.
Return value
- Type:
() => T
createMemo returns a read-only accessor function.
Calling this function returns the current memoized value.
Examples
Basic usage
import { createSignal, createMemo, For } from "solid-js";
const NAMES = ["Alice Smith", "Bob Jones", "Charlie Day", "David Lee"];
function FilterList() { const [query, setQuery] = createSignal("");
// The function executes immediately to calculate the initial value. // It re-executes only when the `query` signal changes. const filteredNames = createMemo(() => { console.log("Calculating list..."); return NAMES.filter((name) => { return name.toLowerCase().includes(query().toLowerCase()); }); });
return ( <div> <input value={query()} onInput={(e) => setQuery(e.currentTarget.value)} placeholder="Search..." />
{/* Accessing the memo. If dependencies haven't changed, returns cached value. */} <div>Count: {filteredNames().length}</div>
<ul> {/* Accessing the memo again does not trigger re-execution. */} <For each={filteredNames()}>{(name) => <li>{name}</li>}</For> </ul> </div> );}Custom equality check
import { createSignal, createMemo, createEffect } from "solid-js";
function DateNormalizer() { const [dateString, setDateString] = createSignal("2024-05-10");
const dateObject = createMemo( () => { return new Date(dateString()); }, undefined, { // Overrides the default strict equality check (===). // If this returns true, observers (like the Effect below) are NOT notified. equals: (prev, next) => { return prev.getTime() === next.getTime(); }, } );
createEffect(() => { // This effect runs only when the numeric time value changes, // ignoring new Date object references. console.log("Date changed to:", dateObject().toISOString()); });
return ( <div> <input value={dateString()} onInput={(e) => setDateString(e.currentTarget.value)} /> {/* Setting the same date string creates a new Date object, but `equals` prevents the update propagation. */} <button onClick={() => setDateString("2024-05-10")}> Reset to the same date </button> </div> );}Accessing previous value
import { createSignal, createMemo } from "solid-js";
function TrendTracker() { const [count, setCount] = createSignal(0);
const trend = createMemo( // The first argument `prev` is the return value of the previous execution. (prev) => { const current = count(); if (current === prev.value) return { value: current, label: "Same" }; return { value: current, label: current > prev.value ? "Up" : "Down", }; }, // The second argument provides the initial value for `prev`. { value: 0, label: "Same" } );
return ( <div> <div>Current: {trend().value}</div> <div>Direction: {trend().label}</div>
<button onClick={() => setCount((c) => c + 1)}>Increment</button> <button onClick={() => setCount((c) => c - 1)}>Decrement</button> </div> );}