[fix] Stop trigger edit forms hydrating from stale cached details - #5606
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
46f8bc7
into
fe-chore/trigger-drawers-split
Fix for a finding on #5571. Targets
fe-chore/trigger-drawers-splitso it lands as part of that PR.Context
Editing a trigger can silently save old values over new ones.
Both edit forms prefill their fields once per id and then latch, so a background refetch cannot overwrite edits in progress. The latch is set as soon as
subscription(orschedule) is non-null. That is the bug: after any mutation the list query is invalidated, and the refetch serves the stale cache first. The form hydrates from that stale copy and marks the id hydrated. When the fresh response lands the effect runs again, hits thehydratedId.current === loadedIdguard, and returns. The fields keep the old values, and saving writes them back.The form had no way to tell.
useTriggerSubscriptionanduseTriggerScheduleexposeisLoading: query.isPending, andisPendingis true only when there is no cached data at all. During a background refetch there is cached data, soisPendingis false.invalidateSubscriptions()andinvalidateSchedules()run after every create, edit, revoke, refresh, remove, and active toggle, so the stale window is easy to land in. Concretely: toggle a trigger off in the list, open its edit drawer straight away, rename it, save. The name change sticks and the active toggle flips back on.Codex flagged this as P1 on
SubscriptionFormand notedScheduleFormshares the pattern. It does, at the identical guard.Changes
Both hooks now return
isFetchingalongsideisLoading:Both forms skip hydration while
isFetchingis true, andisFetchingjoins the effect's dependency list so hydration runs as soon as the fresh result arrives. First load is unaffected: there is no cached data, so the existing!subscriptionguard already covers it.Notes
I could not run
pnpm lint-fix, because the checkout I used has nonode_modules. The hook returns are inferred object literals, so adding a field needs no type changes, and no existing caller destructuresisFetching.What to QA