mono/packages/ui/docs/router.md
2026-03-21 20:18:25 +01:00

71 lines
4.7 KiB
Markdown

# Migration Plan: React Router v6 to TanStack Router
Migrating a large, dynamic application like Polymech from React Router DOM to TanStack Router requires a phased approach. TanStack Router offers superior type safety, built-in scroll restoration, and powerful data loading capabilities, but fundamentally changes how routing is configured (moving away from JSX `<Route>` trees to a static route tree).
## Phase 1: Setup and Basic Configuration
- [ ] **Install Dependencies**
- Run `npm install @tanstack/react-router @tanstack/router-vite-plugin` in `pm-pics`.
- Also install in `@polymech/ecommerce` if needed, or handle it as a peer dependency.
- [ ] **Vite Configuration**
- Add `TanStackRouterVite` to `vite.config.ts`. This enables file-based routing generation or static tree compilation.
- [ ] **Define the Root Route**
- Create `src/routes/__root.tsx`.
- Migrate the layout shell from `AppWrapper` into the Root Route, including:
- `<GlobalDragDrop>`
- `<TopNavigation>` and `<Footer>`
- Context Providers (can stay in `App.tsx` surrounding the router provider, or move to the Root Route context).
- [ ] **Initialize the Router**
- In `src/App.tsx`, remove `<BrowserRouter>` and initialize `const router = createRouter({ routeTree })`.
- Render with `<RouterProvider router={router} />`.
## Phase 2: Route Declaration and Mapping
- [ ] **Convert Static Routes**
- Convert basic pages like `/auth`, `/profile`, `/settings/providers`, `/playground/*`.
- Create route files (e.g., `src/routes/auth.tsx`) or define them in a static route tree file.
- [ ] **Convert Dynamic Routes**
- Map dynamic segments:
- `/post/:id` -> `src/routes/post.$id.tsx`
- `/user/:userId` -> `src/routes/user.$userId.tsx`
- `/tags/:tag` -> `src/routes/tags.$tag.tsx`
- `/collections/:userId/:slug` -> `src/routes/collections.$userId.$slug.tsx`
- Re-wire path parameter extraction from `useParams()` to TanStack's `Route.useParams()`.
- [ ] **Convert Catch-All / Wildcard Routes (Deeply Nested Apps)**
- Routes like `/categories/*` or `/app/filebrowser/*` will need to use TanStack's splat routing (e.g., creating a `$.tsx` file).
- Inside the component, use `Route.useParams()` to grab the `_splat` variable which contains the remaining path string.
- *Refactor Opportunity*: Consider converting deeply nested paths in nested apps (like mount/file/path) into strictly typed Search Parameters (e.g., `?mount=local&path=foo`) leveraging TanStack's built-in Zod validation.
- [ ] **Handle Global Not Found (404)**
- `*` (Not Found) needs to be handled via TanStack Router's built-in `NotFoundRoute` or router configuration, not a standard route definition.
- [ ] **Migrate Standalone Packages**
- `@polymech/ecommerce` (`EcommerceBundle.tsx`) relies on `react-router-dom` (`useLocation`, `matchPath`, `Navigate`).
- It needs to be refactored either entirely to TanStack Router, or decoupled so the host app injects the routing logic.
## Phase 3: Component Refactoring (The Long Tail)
- [ ] **Replace `useNavigate`**
- Find all instances of `useNavigate()` from `react-router-dom`.
- Replace with `useNavigate()` from `@tanstack/react-router`.
- **Crucial**: TanStack requires paths to match the route definitions strictly, which will catch broken links but requires updating all link definitions.
- [ ] **Replace `<Link>`**
- Update all `react-router-dom` `<Link to="...">` with TanStack's `<Link to="...">`.
- [ ] **Replace `useLocation` and `useSearchParams`**
- TanStack has robust typed search parameters. If `useSearchParams` is used for view modes, filtering, or tabs, define the search params schema on the Route level.
- [ ] **Replace `<Navigate>` components**
- Change programmatic `<Navigate to="..."/>` to TanStack's equivalent or throw a redirect inside a route loader.
## Phase 4: Enhancements (Optional but Recommended)
- [ ] **Implement Pre-fetching**
- Move API calls currently wrapped in `useQuery` inside `useEffect` (like home feed loading) into TanStack's `loader` functions. This eliminates waterfalls.
- [ ] **Configure Scroll Restoration**
- Remove the custom `ScrollRestoration.tsx`.
- Enable `<ScrollRestoration />` provided by TanStack in the Root Route.
- [ ] **Analytics Interception**
- Hook analytics into the router context directly (e.g., `router.subscribe`), replacing the `onRouteChange` prop we added to the custom restorer.
## Risk Assessment
- **Huge API surface change**: Touches roughly 30-50 files.
- **Ecommerce Package**: The `@polymech/ecommerce` bundle must be updated carefully so it still functions if imported independently.
- **Type errors**: Prepare for hundreds of TypeScript errors regarding route typings immediately after enabling the Vite plugin.