diff --git a/packages/react-router/tests/routeContext.test.tsx b/packages/react-router/tests/routeContext.test.tsx index eef424c867f..e42b10d6035 100644 --- a/packages/react-router/tests/routeContext.test.tsx +++ b/packages/react-router/tests/routeContext.test.tsx @@ -9,6 +9,7 @@ import { import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' import { z } from 'zod' +import { useEffect } from 'react' import { Link, Outlet, @@ -2475,6 +2476,61 @@ describe('useRouteContext in the component', () => { expect(content).toBeInTheDocument() }) + test('route context, (sleep in beforeLoad), with immediate navigation', async () => { + const contextValues: Array<{ data: string }> = [] + + const rootRoute = createRootRoute({ + beforeLoad: async () => { + await sleep(WAIT_TIME) + return { data: 'context-from-beforeLoad' } + }, + component: () => { + const context: { data: string } = rootRoute.useRouteContext() + + // Track all context values we receive + contextValues.push(context) + + return + }, + }) + + function Component() { + const navigate = indexRoute.useNavigate() + + // Navigate away immediately on mount + useEffect(() => { + navigate({ to: '/other' }) + }, [navigate]) + + return
Index page
+ } + + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: Component, + }) + + const otherRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/other', + component: () =>
Other page
, + }) + + const routeTree = rootRoute.addChildren([indexRoute, otherRoute]) + const router = createRouter({ routeTree, history }) + + render() + + // Wait for navigation to complete + await screen.findByText('Other page') + + const allContextsValid = contextValues.every( + (c) => c.data === 'context-from-beforeLoad', + ) + expect(allContextsValid).toBe(true) + }) + test('route context (sleep in loader), present in the index route', async () => { const rootRoute = createRootRoute({}) const indexRoute = createRoute({ diff --git a/packages/solid-router/tests/routeContext.test.tsx b/packages/solid-router/tests/routeContext.test.tsx index b83022f7dc4..b7e0a902a91 100644 --- a/packages/solid-router/tests/routeContext.test.tsx +++ b/packages/solid-router/tests/routeContext.test.tsx @@ -2,6 +2,7 @@ import { cleanup, fireEvent, render, screen } from '@solidjs/testing-library' import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' import { z } from 'zod' +import { createEffect, onMount } from 'solid-js' import { Link, Outlet, @@ -2392,6 +2393,64 @@ describe('useRouteContext in the component', () => { expect(content).toBeInTheDocument() }) + // Note: This test passes in solid-router but fails in react-router, even + // though in issue (GitHub #6040), the bug manifests in both routers. + test('route context, (sleep in beforeLoad), with immediate navigation', async () => { + const contextValues: Array<{ data: string }> = [] + + const rootRoute = createRootRoute({ + beforeLoad: async () => { + await sleep(WAIT_TIME) + return { data: 'context-from-beforeLoad' } + }, + shellComponent: () => { + const context = rootRoute.useRouteContext() + + // Track context value at render time + createEffect(() => { + const contextValue: { data: string } = context() + contextValues.push(contextValue) + }) + + return + }, + }) + + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: () => { + const navigate = indexRoute.useNavigate() + + // Navigate away immediately on mount + onMount(() => { + navigate({ to: '/other' }) + }) + + return
Index page
+ }, + }) + + const otherRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/other', + component: () =>
Other page
, + }) + + const routeTree = rootRoute.addChildren([indexRoute, otherRoute]) + const router = createRouter({ routeTree, history }) + + render(() => ) + + // Wait for navigation to complete + await screen.findByText('Other page') + + const allContextsValid = contextValues.every( + (c) => c.data === 'context-from-beforeLoad', + ) + expect(allContextsValid).toBe(true) + }) + test('route context (sleep in loader), present root route', async () => { const rootRoute = createRootRoute({ loader: async () => {