A primitive for creating a mutable store, an alternative to createStore.
| Stage | Category | Version | Last Updated | Demo |
|---|---|---|---|---|
| 3 | Reactivity | 3.0.0-next.2 (next) | Aug 13, 2026 | Demo → |
npm i @solid-primitives/mutable@nextA primitive for creating a mutable store proxy object. A compatibility layer for code that relies on direct mutation semantics (similar to MobX/Vue reactivity).
- Docs (Storybook)
createMutable- Creates a mutable store proxy object.modifyMutable- Helper for applying multiple mutations to a mutable store in one call.
createMutable
import { createMutable } from "@solid-primitives/mutable";
declare function createMutable<T extends object>(state: T, options?: {}): T;Creates a new mutable Store proxy object. Stores only trigger updates on values changing. Tracking is done by intercepting property access and automatically tracks deep nesting via proxy.
Useful for integrating external systems or as a compatibility layer with MobX/Vue.
Note: A mutable state can be passed around and mutated anywhere, which can make it harder to follow and easier to break unidirectional flow. It is generally recommended to use
createStoreinstead.
const state = createMutable(initialValue);
// read valuestate.someValue;
// set valuestate.someValue = 5;
state.list.push(anotherValue);Mutables support setters along with getters.
const user = createMutable({ firstName: "John", lastName: "Smith", get fullName() { return `${this.firstName} ${this.lastName}`; }, set fullName(value) { [this.firstName, this.lastName] = value.split(" "); },});Only plain objects and arrays are deep-proxied. Class instances (e.g. Date, Map, Set) are stored and returned as-is.
Reactivity and flushing
Signal writes are automatically batched to the next microtask. Reads outside a reactive context (effects, memos, JSX) always reflect the latest written value immediately without waiting for a flush.
In tests, call flush() (from solid-js) after writes to synchronously apply pending updates before asserting on reactive state:
import { flush } from "solid-js";import { createMutable } from "@solid-primitives/mutable";
const state = createMutable({ count: 0 });
createEffect( () => state.count, value => console.log(value),);flush(); // runs initial effect
state.count = 1;flush(); // applies update, re-runs effectmodifyMutable
import { modifyMutable } from "@solid-primitives/mutable";
declare function modifyMutable<T>(state: T, modifier: (state: T) => void): void;Applies multiple mutations to a mutable Store via a single modifier function. The modifier receives the mutable proxy (or nested proxy) directly and mutates it in place. Because all signal writes are automatically batched, dependent computations update once after the modifier returns.
const state = createMutable({ user: { firstName: "John", lastName: "Smith", },});
// Modify two fields — single reactive updatemodifyMutable(state.user, u => { u.firstName = "Jake"; u.lastName = "Johnson";});Changelog
See CHANGELOG.md