Repository navigation
fix(react-router): a route that renders <Outlet /> renders nothing of its own - #2670
Merged
Merged
Conversation
…of its own
A route with no element renders an `<Outlet />`, and JSX routes already read
`element={<Outlet />}` that way. Route objects did not:
- `element: <Outlet />` and `Component: Outlet` made `Outlet` the route's
page and the layout of every route inside it. Those `layout:Outlet`
references link nothing: 93 failed rows on Medusa's admin dashboard, 106
on Mercur's, 87 on mercurjs/vendor-panel.
- A `lazy` loader returning `{ Component: Outlet, loader }` (Medusa's `:id`
routes import their page module only for its loader and breadcrumb) read
as unreadable, so the route fell back to that module's page, which became
the layout of the routes inside: a product's detail page drawn around its
variants' pages.
Such a route object is now an `outlet` scope. It is a route at its own
address, so a navigation there still lands, and it sits inside the layouts
around it, but it has no page reference and is no layout. A page inside at
the same address claims the address as before, and a `path: ''` one only
groups its children at its parent's address. `lazyRouteReference` returns
`Outlet` for a loader that hands it back, and the JSX branch drops it the way
it drops `element={<Outlet />}`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up 1 of #2668.
Problem
A React Router route with no element renders an
<Outlet />. JSX routes already readelement={<Outlet />}as rendering nothing of their own. Route objects did not:element: <Outlet />andComponent: OutletmadeOutletthe route's page and the layout of every route inside it. Thoselayout:Outletreferences link nothing. On current main they are 93 failed rows on Medusa's admin dashboard, 106 on Mercur's admin panel and 87 on mercurjs/vendor-panel.lazyloader returning{ Component: Outlet, loader }. Medusa's:idroutes import their page module only for itsloaderand breadcrumb. The loader reader (fix(react-router): a lazy route links the page its loader picks #2480) couldn't read that, so the route fell back to the module the loader imports. That module's page became the layout of the routes inside it:/products/:id/variants/:variant_idand its five children were drawn insideProductDetail. That made 13 wrong layout edges on Medusa and 5 on each Mercur panel, the extras fix(react-router): read the table a function returns when a variable hands it to the router #2668's oracle flagged.Fix (
frameworks/react.ts)Outlet(element: <Outlet />,Component: Outlet, or a loader handing back{ Component: Outlet }or{ element: <Outlet /> }) becomes anoutletscope:{ path: 'approvals', element: <Outlet /> }that its shell draws itself. A first version dropped these routes, and the corpus A/B below caught it.{ path: 'regions', element: <Outlet />, children: [{ path: '', … }] }).path: '') it only groups its children. React Router's error-boundaries example writes this to hold anerrorElement, and the parent stays the page there. JSX already treats<Route path="" element={<Outlet />}>this way.lazyRouteReferencereturnsOutletfor a loader that hands it back. Before, that loader fell back to its first import. The JSX branch dropsOutletthe way it dropselement={<Outlet />}.Verification
Regression test.
__tests__/react-router-outlet-routes.test.tscovers Medusa's shapes (element: <Outlet />andComponent: Outletparents,:idloaders returningComponent: Outletandelement: <Outlet />), addresses only the shell draws, a navigation to each, and the error-boundaries shape:654a853f), 2 of its 3 tests fail: the wrong layouts, and the leftoverOutletroute refs.Outletas their component fails 1 test;Outletfails 1;path: ''outlet a route of its own fails 2.Checks.
tsc --noEmitis clean, and the React Router and React test files pass. Full suite with the kernel built andCODEGRAPH_KERNEL_EXPECT=1,--maxWorkers=4: 7,479 passed, 0 failed, 80 skipped, on654a853fplus this branch. After syncing #2669 (3695818f, a sync-time import retry):tsc, 11 React Router and sync-import test files (178 tests), and a re-index of Medusa, both Mercur panels, rr-examples and outline with the synced build, byte-identical to the pre-sync dumps.A/B on real repos
Same kit as #2668: fresh
codegraph initwith the kernel, current main654a853fagainst this branch; onlyreact.jsdiffers.packages/admin/dashboardProductDetail,ProductOptionDetailandTaxRegionDetailaround their:idroute's other children), 6 more re-attributed to the''child that really rendersTaxRegionDetail(same edge, newrefName), all 93layout:Outletrows goneProductDetailaround the variant routes), all 106layout:Outletrows gonelayout:Outletrows goneexamples/error-boundaries/is theLayoutroute linked toLayout, instead of thepath: ''child linked to React Router's ownOutletfunction; its 1layout:Outletrow goneextract()over 2,677 distinct router files from four GitHub code-search corpora changes 10 files. It only drops 40 references: 24layout:Outletand 16Outletpage refs. No route is added or removed.🤖 Generated with Claude Code