Flow Studio
Making Custom Actions Undoable
To make a new workflowStore action undoable, wrap its state mutation inside historyAction(). The wrapper takes a pre-mutation snapshot, pushes it to the undo stack, and clears the redo stack before executing the mutation.
The historyAction Wrapper
// historyAction is exposed as part of the workflowStore state
// It is added by historyMiddleware and available on the store
historyAction: (fn: () => void) => void
// Usage pattern:
myNewAction: (param: string) => {
get().historyAction(() => {
set(state => ({
// ... your state mutation here
}));
});
}
Example: Adding a Custom "Duplicate Node" Action
// Add to workflowStore actions
duplicateNode: (nodeId: string) => {
get().historyAction(() => {
const { nodes } = get();
const original = nodes.find(n => n.id === nodeId);
if (!original) return;
const duplicate: WorkflowNode = {
...original,
id : crypto.randomUUID(),
position: { x: original.position.x + 40, y: original.position.y + 40 },
data : JSON.parse(JSON.stringify(original.data)) // deep copy config
};
set(state => ({ nodes: [...state.nodes, duplicate] }));
});
}
// Now duplicateNode is undoable with Ctrl+Z
// The snapshot before duplication is stored → undo removes the duplicate
Example: "Add Comment Node" (Non-Executable Node)
addCommentNode: (text: string, position: XYPosition) => {
get().historyAction(() => {
set(state => ({
nodes: [...state.nodes, {
id : crypto.randomUUID(),
type : 'CommentNode',
position,
data : { label: text, config: {}, inputPorts: [], outputPorts: [] }
}]
}));
});
}
Decision Guide: Should My Action Use historyAction?
| Does it mutate nodes[] or edges[]? | Is it reversible from the user's perspective? | Use historyAction? |
|---|---|---|
| Yes | Yes | Yes |
| Yes (config-only) | Auto-saved to server — user uses Reset instead | No |
| No (viewport, mode) | N/A | No |
| No (external side effects only) | N/A — side effects cannot be undone by snapshot | No |
historyAction only snapshots nodes[] and edges[]. If your action has external side effects (API calls, notifications, state in other stores), historyAction will NOT roll those back on undo. Only use historyAction for pure in-memory graph mutations.