From 2af79012e46045f175ae26bcf1bea4738b6ab191 Mon Sep 17 00:00:00 2001 From: Steve Dudenhoeffer Date: Sat, 22 Aug 2026 19:36:51 -0400 Subject: [PATCH] Address #124 review: a failed history refetch must not undo anything MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gadfly (error-handling lens): react-query keeps the stale pages in `data` when a refetch fails, so `useUndoLast` would fall through and revert the step BEFORE the one just made — the exact outcome the refetch exists to prevent. Bail out with a toast unless the refetch succeeded. Co-Authored-By: Claude Fable 5 --- web/src/editor/useUndoLast.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/web/src/editor/useUndoLast.ts b/web/src/editor/useUndoLast.ts index 279bcfe..a21c315 100644 --- a/web/src/editor/useUndoLast.ts +++ b/web/src/editor/useUndoLast.ts @@ -1,4 +1,5 @@ import { useCallback } from 'react' +import { toast } from '@/components/ui/toast' import { totalChanges, useGardenHistory, useUndo, type ChangeSet } from '@/lib/history' /** The newest change set still in effect — not already reverted, and not itself @@ -23,10 +24,16 @@ export function useUndoLast(gardenId: number, enabled: boolean) { const undoLast = useCallback(async () => { const fresh = await history.refetch() - const list = fresh.data?.pages.flatMap((p) => p.changeSets) ?? sets - const t = latestUndoable(list) + // A failed refetch keeps the STALE pages in `data` (react-query doesn't + // clear them), so falling through here would pick the step before the one + // just made. Undoing nothing is the only safe answer until it can be read. + if (fresh.status !== 'success') { + toast.error("Couldn't re-read the history, so nothing was undone — try again.") + return + } + const t = latestUndoable(fresh.data.pages.flatMap((p) => p.changeSets)) if (t) undo.undo(t) - }, [history, undo, sets]) + }, [history, undo]) return { history,