Signals
Edit this pageSignals are the primary means of managing state in your Solid application. They provide a way to store and update values, and are the foundation of reactivity in Solid.
Signals can be used to represent any kind of state in your application, such as the current user, the current page, or the current theme. This can be any value, including primitive values such as strings and numbers, or complex values such as objects and arrays.
Creating a signal
You can create a signal by calling the createSignal function, which is imported from solid-js.
This function takes an initial value as an argument, and returns a pair of functions: a getter function, and a setter function.
import { createSignal } from "solid-js";
const [count, setCount] = createSignal(0);// ^ getter ^ setterThe syntax using [ and ] is called array destructuring.
This lets you extract values from the array.
In the context of createSignal, the first value is the getter function, and the second value is the setter function.
Accessing values
The getter function returned by createSignal is used to access the value of the signal.
You call this function with no arguments to get the current value of the signal:
console.log(count()); // output: 0Updating values
The setter function returned by createSignal is used to update the value of the signal.
This function takes an argument that represents the new value of the signal:
setCount(count() + 1);The setter function can also take a function that passes the previous value:
setCount((prevCount) => prevCount + 1);In Solid 2.0, calling a setter queues the update rather than applying it immediately. The new value becomes visible after the microtask flush:
const [count, setCount] = createSignal(0);
setCount(1);console.log(count()); // still 0 — update is queued
flush();console.log(count()); // now 1Within reactive scopes (effects, memos, JSX), this is handled automatically — your UI will always reflect the latest value. You only need flush() in imperative code where you need the value synchronously.
Reactivity
Signals are reactive, which means that they automatically update when their value changes. When a signal is called within a tracking scope, the signal adds the dependency to a list of subscribers. Once a signal's value changes, it notifies all of its dependencies of the change so they can re-evaluate their values and update accordingly.
function Counter() { const [count, setCount] = createSignal(0); const increment = () => setCount((prev) => prev + 1);
return ( <div> <span>Count: {count()}</span> {/* Updates when `count` changes */} <button type="button" onClick={increment}> Increment </button> </div> );}A tracking scope can be created by createEffect or createMemo, which are other Solid primitives.
Both functions subscribe to the signals accessed within them, establishing a dependency relationship. Once this relationship is established, the function is notified whenever the signal changes.
Derived signals (function-form createSignal)
In Solid 2.0, createSignal can accept a function as its first argument instead of a static value. This creates a writable derived signal — sometimes called a "writable memo". The function is used to compute the signal's value reactively, and the setter can override it:
import { createSignal } from "solid-js";
const [count, setCount] = createSignal(0);
// derived: automatically tracks `count` and doubles itconst [doubled] = createSignal(() => count() * 2);
console.log(doubled()); // 0
setCount(5);// After flush, doubled() will be 10This replaces many patterns that previously used createComputed for "write-back" derived values.
For read-only derived values, prefer createMemo.
Writes under owned scope
Writing to signals inside a reactive scope (effects, memos, component body) will produce a dev warning in Solid 2.0. Signal writes belong in event handlers, onSettled, or untracked blocks.
// ❌ warns: writing from inside a memocreateMemo(() => setDoubled(count() * 2));
// ✅ derive instead of writing backconst doubled = createMemo(() => count() * 2);For rare cases where a signal must be written from within scope (e.g. internal component flags), opt in with { pureWrite: true }:
const [ref, setRef] = createSignal(null, { pureWrite: true });To learn more about how to use Signals in your application, visit our state management guide.