Skip to main content
Version: 3.1.0

Router Recreated Mid-Navigation Causes Frozen UI After Save

Version: 3.1.0 Date: 2026-06-12

Goal: Fix a race condition where saving a source or storage left the UI frozen on the edit screen — URL changed correctly but the page stayed stuck and the Save button was grayed out.

Solution: createBrowserRouter was called inside App with routes(state.data), so every re-render of App produced a new router instance. The onSuccess callback in StepStorageForm invalidated ['status'], which triggered a re-render of App and a new router while the navigate('/workflows') transition was still in flight. The new router initialized on the old URL, the old router finished pushing the new URL, and the two were forever desynchronized. Fix: create the router exactly once at module level (const router = routes()). ActivatedRoute now reads status itself via useQuery(['status']) instead of receiving it as a prop from the router.

Files Modified:

  • ui/src/App.tsx — router created once at module level, removed useQuery(['status']) from App
  • ui/src/routes.tsxroutes() takes no arguments; ActivatedRoute reads ['status'] via useQuery internally
  • README.md — added "Router singleton" convention note under UI architecture section