Skip to content

Add undo/redo/reset chain to useUpdateFragment #214

Description

@jho406

useUpdateFragment currently fires and forgets — once you update a fragment, there's no way to walk it back without manually dispatching the previous state. This makes optimistic UI patterns tedious.

Proposed API

update() returns a chainable object with the fragment bound and an internal undo/redo stack:

const update = useUpdateFragment()

// Chain multiple updates
const cart = update(cartRef, (draft) => { draft.quantity = 5 })
  .update((draft) => { draft.quantity = 10 })
  .update((draft) => { draft.color = 'red' })

// Walk backward/forward
cart.undo()  // back to q=10
cart.undo()  // back to q=5
cart.redo()  // forward to q=10

// Discard everything this chain did
cart.reset() // back to state before the chain started

Behavior

  • The first call update(ref, updater) binds the fragment and starts the chain
  • Each method returns a new chain object with the stack curried in
  • Every update, undo, redo, and reset dispatches updateFragment immediately
  • undo() at the bottom of the stack is a no-op (no dispatch)
  • redo() at the top of the stack is a no-op (no dispatch)
  • update() after undo() clears the redo stack (standard undo/redo semantics)
  • reset() restores the state from before the chain started and clears the stack

Use case: optimistic UI

const update = useUpdateFragment()
const cart = update(cartRef, (draft) => { draft.items.push(item) })

try {
  await remote('/cart', { method: 'POST', body: item })
} catch {
  cart.reset()
}

Getting started

git checkout v2
cd superglue/superglue
npm install
npx vitest run spec/lib/useSetFragment.spec.jsx # existing tests

When opening your PR, target the v2 branch.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions