Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/fix-beforeload-null-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@tanstack/router-core': patch
---

fix(router-core): treat null return from beforeLoad as no-op for route context

When `beforeLoad` returns `null`, it is now treated the same as `undefined` (no-op) instead of being stored as `__beforeLoadContext: null`. This is consistent with how the `context` route option already handles null returns via `?? undefined`, and prevents null from silently interfering with context accumulation.

Fixes #7110
36 changes: 36 additions & 0 deletions packages/react-router/tests/routeContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2630,6 +2630,42 @@ describe('useRouteContext in the component', () => {
expect(content).toBeInTheDocument()
})

test('route context preserved when beforeLoad returns null', async () => {
const rootRoute = createRootRoute({
beforeLoad: () => null,
component: () => {
const context = rootRoute.useRouteContext()
return <div>{JSON.stringify(context)}</div>
},
})
const routeTree = rootRoute.addChildren([])
const router = createRouter({ routeTree, history, context: { foo: 'bar' } })

render(<RouterProvider router={router} />)

const content = await screen.findByText(JSON.stringify({ foo: 'bar' }))

expect(content).toBeInTheDocument()
})

test('route context preserved when async beforeLoad returns null', async () => {
const rootRoute = createRootRoute({
beforeLoad: async () => null,
component: () => {
const context = rootRoute.useRouteContext()
return <div>{JSON.stringify(context)}</div>
},
})
const routeTree = rootRoute.addChildren([])
const router = createRouter({ routeTree, history, context: { foo: 'bar' } })

render(<RouterProvider router={router} />)

const content = await screen.findByText(JSON.stringify({ foo: 'bar' }))

expect(content).toBeInTheDocument()
})

test('route context (sleep in beforeLoad), present in the root route', async () => {
const rootRoute = createRootRoute({
beforeLoad: async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/router-core/src/load-matches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ const executeBeforeLoad = (
}

const updateContext = (beforeLoadContext: any) => {
if (beforeLoadContext === undefined) {
if (beforeLoadContext === undefined || beforeLoadContext === null) {
inner.router.batch(() => {
pending()
resolve()
Expand Down
Loading