createSignal
createSignal
is the fundamental reactive primitive in Solid. It creates a signal with a getter and setter.
Definition
type Signal<T> = [get: Accessor<T>, set: Setter<T>];
function createSignal<T>(): Signal<T | undefined>;// `createSignal` can also accept initial value as a parameterfunction createSignal<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;// or it can accept another signal (see `Derived Signals` example)function createSignal<T>( fn: ComputeFunction<T>, initialValue?: T, options?: SignalOptions<T>): Signal<T>;
interface SignalOptions<T> { name?: string; equals?: ((prev: T, next: T) => boolean) | false;}
Basic Usage
import { createSignal } from "solid-js";
function Counter() { const [count, setCount] = createSignal(0);
return <button onClick={() => setCount((c) => c + 1)}>{count()}</button>;}
Derived Signals
Signals can be derived from other signals. This is useful for creating derived state that can be updated locally, and also resets when dependencies update.
import { createSignal } from "solid-js";
function Child(props: { count: number }) { const [childCount, setChildCount] = createSignal(() => props.count);
return <button onClick={() => setChildCount((c) => c + 1)}>{childCount()}</button>;}
function Parent() { const [count, setCount] = createSignal(0);
return ( <div> <Child count={count()} /> <button onClick={() => setCount(0)}>Reset</button> </div> );}
Here updating count
will also update childCount
, but updating childCount
will not affect count
.
equals
parameter
You can pass equals
parameter to customize signal update behavior. By default values compared with ===
, however you can set your own behavior:
function CustomEqualsExample() { const [value, setValue] = createSignal(0, { // Do not update signal when we value is more than 5 equals: (_prev, next) => next > 5, });
return ( <section> <p>Value will not be more than (5): {value()}</p> <button onClick={() => setValue((value) => value + 1)}>Increase value</button> </section> );}
Special case equals: false
There are special cases when you might need to pass equals: false
.
For instance, you might want to implement refetch functioanlity:
import { createSignal, createAsync, isPending, Suspense } from "solid-js";
const fetchRandomNumber = () => new Promise<number>((resolve) => { setTimeout(() => resolve(Math.random()), 1000); });
function RefetchExample() { const [refetchSignal, refetch] = createSignal(undefined, { equals: false }); const randomNumber = createAsync(() => { // subscribe to refetch signal refetchSignal();
return fetchRandomNumber(); });
return ( <section> <p> Random number:{" "} <Suspense fallback="Loading number..."> <Show when={!isPending(randomNumber)} fallback="Refetching number..."> {randomNumber()} </Show> </Suspense> </p> <button onClick={refetch} disabled={isPending(randomNumber)}>Refetch number</button> </section> );}
Another usecase is when you want to reduce memory allocation. In Solid (in comparison to React) signals can be mutable. In the following example we don't need to create a new object every time to update the signal. Instead, we can just mutate the object. If you build high-load app, this trick can help you to optimize memory and GC calls.
function SignalMutationExample() { // Calling `updateObject` will always trigger the signal const [object, updateObject] = createSignal({ value: 0 }, { equals: false });
return ( <section> <p>Object value: {object().value}</p> <button onClick={() => updateObject((object) => { // Here we're not creating new object // Instead we just mutate the value inside object.value++;
return object; }) } > Increase object value </button> </section> );}
You should be careful with equals: false
, because it may lead to unnecessary signal triggers which can lead to unnecessary computations.
Last updated: 5/3/25, 3:34 AM
Edit this page on GitHub