Skip to content

Patches & Devtools

Immer patches for undo/redo and syncing, plus the state inspector panel.

Every update can produce Immer patches, a small description of exactly what changed. Undo/redo, syncing and the devtools are built on them. They are only built while something is listening, so they cost nothing the rest of the time.

import { applyPatchesToStore } from "@nice-code/state";
// Listen to patches for every update
const stop = store.listenToPatches((patches, inversePatches) => {
sendToServer(patches);
});
// Or collect patches for a single update
store.update((s) => { s.count += 1; }, (patches, inverse) => {
undoStack.push(inverse);
});
// Apply patches (received from elsewhere, or to undo)
store.applyPatches(patches);

Inverse patches are how undo works: keep a stack of them, and applyPatches the top one to undo the last change.

An inspector for your stores, with no setup: a timeline of changes, before/after diffs, a live view of your state you can edit directly, and one-click undo using patches. Name the stores you want to observe. Nothing renders inside your app.

devtools.ts
import { createNiceDevtools } from "@nice-code/devtools";
import { counterStore } from "./counterStore";
export const devtools = createNiceDevtools({
topologyId: "my-app",
stores: { counterStore }, // the key is the label the panel shows
});

To add a store you create later, call devtools.registerStore("label", store).

You rarely need the pieces underneath. createNiceDevtools records changes in a StateDevtoolsCore and sends them to the devtools window with stateBridgeScope. Both are exported from @nice-code/state/devtools/browser if you wire a devtools host by hand.

The panel appears in the devtools window. There you can filter by store, inspect and edit live state, view the diff and patches for each change, pause the timeline, and revert a change using its inverse patches.

Registering a store attaches a patch listener, which costs next to nothing in development. Keep devtools setup out of production bundles.

EntryContents
@nice-code/stateStore, update, applyPatchesToStore, core types
@nice-code/state/reactuseStoreState, useLocalStore, InjectStoreState
@nice-code/state/devtools/browserStateDevtoolsCore, stateBridgeScope, NiceStateDevtools