AI agents: fetch the documentation index at llms.txt. Markdown versions are available by appending .md to any page URL, including this page's markdown.
Undo and redo
Client-side undo and redo with full transaction history.
await client.create("Task", { title: "Task 1", status: "todo" });
await client.update("Task", "task-123", { title: "Updated" });
if (client.canUndo()) {
await client.undo();
}
if (client.canRedo()) {
await client.redo();
}Returns true if the undo stack has entries.
const canUndo: boolean = client.canUndo();Returns true if the redo stack has entries.
const canRedo: boolean = client.canRedo();Applies the inverse of the last mutation and moves it to the redo stack.
await client.undo();On failure, the entry stays on the undo stack and the error is thrown.
Re-applies the last undone mutation and moves it back to the undo stack.
await client.redo();Each mutation creates a history entry with inverse and original operations. undo() executes the inverse as a new outbox transaction (with history recording suppressed). redo() works the same way in reverse.
See Transactions for the complete action-to-inverse mapping.
Undo/redo operations create real transactions that sync to the server: not client-only rollbacks.
clearAll() clears both stacksUse the sync client hooks in @stratasync/react to bind undo/redo to your UI.
import { useSyncClientInstance } from "@stratasync/react";
function UndoRedoButtons() {
const client = useSyncClientInstance();
return (
<div>
<button onClick={() => client.undo()} disabled={!client.canUndo()}>
Undo
</button>
<button onClick={() => client.redo()} disabled={!client.canRedo()}>
Redo
</button>
</div>
);
}Bind Cmd/Ctrl+Z and Cmd/Ctrl+Shift+Z to undo and redo.
import { useEffect } from "react";
import { useSyncClientInstance } from "@stratasync/react";
function useUndoRedoShortcuts() {
const client = useSyncClientInstance();
useEffect(() => {
const handler = (e: KeyboardEvent) => {
if (!(e.metaKey || e.ctrlKey)) return;
if (e.key === "z" && !e.shiftKey) {
e.preventDefault();
client.undo();
} else if (e.key === "z" && e.shiftKey) {
e.preventDefault();
client.redo();
}
};
window.addEventListener("keydown", handler);
return () => window.removeEventListener("keydown", handler);
}, [client]);
}