diff --git a/e2e/react-start/basic/src/routes/__root.tsx b/e2e/react-start/basic/src/routes/__root.tsx
index 81e9c96855..d8fc0d3b24 100644
--- a/e2e/react-start/basic/src/routes/__root.tsx
+++ b/e2e/react-start/basic/src/routes/__root.tsx
@@ -1,11 +1,13 @@
///
import * as React from 'react'
import {
+ ClientOnly,
HeadContent,
Link,
Outlet,
Scripts,
createRootRoute,
+ useRouterState,
} from '@tanstack/react-router'
import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary'
@@ -92,6 +94,11 @@ const RouterDevtools =
)
function RootDocument({ children }: { children: React.ReactNode }) {
+ const { isLoading, status } = useRouterState({
+ select: (state) => ({ isLoading: state.isLoading, status: state.status }),
+ structuralSharing: true,
+ })
+
return (
@@ -209,6 +216,12 @@ function RootDocument({ children }: { children: React.ReactNode }) {
+
+
+ {isLoading ? 'true' : 'false'}
+ {status}
+
+
{children}
This is an inline styled div
diff --git a/e2e/react-start/basic/tests/redirect.spec.ts b/e2e/react-start/basic/tests/redirect.spec.ts
index 1915388b0d..34ba7b6ea9 100644
--- a/e2e/react-start/basic/tests/redirect.spec.ts
+++ b/e2e/react-start/basic/tests/redirect.spec.ts
@@ -1,5 +1,5 @@
import queryString from 'node:querystring'
-import { expect } from '@playwright/test'
+import { expect, type Page } from '@playwright/test'
import combinateImport from 'combinate'
import {
getDummyServerPort,
@@ -15,6 +15,19 @@ const e2ePortKey = getE2EPortKey()
const PORT = await getTestServerPort(e2ePortKey)
const EXTERNAL_HOST_PORT = await getDummyServerPort(e2ePortKey)
+const POSTS_URL = `http://localhost:${PORT}/posts`
+
+async function waitForRouterIdle(page: Page) {
+ await expect(page.getByTestId('router-isLoading')).toHaveText('false')
+ await expect(page.getByTestId('router-status')).toHaveText('idle')
+}
+
+async function waitForPostsIndex(page: Page) {
+ await page.waitForURL(POSTS_URL)
+ expect(page.url()).toBe(POSTS_URL)
+ await waitForRouterIdle(page)
+ await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+}
test.describe('redirects', () => {
test.describe('internal', () => {
@@ -37,7 +50,7 @@ test.describe('redirects', () => {
`via-${thrower}${reloadDocument ? '-reloadDocument' : ''}`,
)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
let requestHappened = false
const requestPromise = new Promise((resolve) => {
@@ -65,10 +78,7 @@ test.describe('redirects', () => {
await link.click()
- const url = `http://localhost:${PORT}/posts`
- await page.waitForURL(url)
- expect(page.url()).toBe(url)
- await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+ await waitForPostsIndex(page)
expect(fullPageLoad).toBe(reloadDocument)
})
},
@@ -84,12 +94,8 @@ test.describe('redirects', () => {
page,
}) => {
await page.goto(`/redirect/internal/via-${thrower}`)
- await page.waitForLoadState('networkidle')
-
- const url = `http://localhost:${PORT}/posts`
- expect(page.url()).toBe(url)
- await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+ await waitForPostsIndex(page)
})
})
})
@@ -110,7 +116,7 @@ test.describe('redirects', () => {
if (scenario === 'navigate') {
await page.goto(`/redirect/external?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const link = page.getByTestId(`via-${thrower}`)
await link.focus()
await link.click()
@@ -147,7 +153,7 @@ test.describe('redirects', () => {
if (scenario === 'navigate') {
await page.goto(`/redirect/${target}/serverFn?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const link = page.getByTestId(
`via-${thrower}${reloadDocument ? '-reloadDocument' : ''}`,
@@ -158,7 +164,7 @@ test.describe('redirects', () => {
})
await link.focus()
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
await link.click()
} else {
await page.goto(`/redirect/${target}/serverFn/via-${thrower}?${q}`)
@@ -166,7 +172,7 @@ test.describe('redirects', () => {
const url =
target === 'internal'
- ? `http://localhost:${PORT}/posts`
+ ? POSTS_URL
: `http://localhost:${EXTERNAL_HOST_PORT}/`
await page.waitForURL(url)
@@ -174,6 +180,7 @@ test.describe('redirects', () => {
expect(page.url()).toBe(url)
if (target === 'internal' && scenario === 'navigate') {
+ await waitForRouterIdle(page)
await expect(
page.getByTestId('PostsIndexComponent'),
).toBeInViewport()
@@ -201,7 +208,7 @@ test.describe('redirects', () => {
await page.goto(`/redirect/${target}/serverFn/via-useServerFn?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const button = page.getByTestId('redirect-on-click')
@@ -214,11 +221,12 @@ test.describe('redirects', () => {
const url =
target === 'internal'
- ? `http://localhost:${PORT}/posts`
+ ? POSTS_URL
: `http://localhost:${EXTERNAL_HOST_PORT}/`
await page.waitForURL(url)
expect(page.url()).toBe(url)
if (target === 'internal') {
+ await waitForRouterIdle(page)
await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
expect(fullPageLoad).toBe(reloadDocument)
}
diff --git a/e2e/solid-start/basic/src/routes/__root.tsx b/e2e/solid-start/basic/src/routes/__root.tsx
index 549f10e579..c517867dab 100644
--- a/e2e/solid-start/basic/src/routes/__root.tsx
+++ b/e2e/solid-start/basic/src/routes/__root.tsx
@@ -1,10 +1,12 @@
///
import {
+ ClientOnly,
HeadContent,
Link,
Outlet,
Scripts,
createRootRoute,
+ useRouterState,
} from '@tanstack/solid-router'
import { TanStackRouterDevtoolsInProd } from '@tanstack/solid-router-devtools'
@@ -65,6 +67,10 @@ export const Route = createRootRoute({
})
function RootComponent() {
+ const routerState = useRouterState({
+ select: (state) => ({ isLoading: state.isLoading, status: state.status }),
+ })
+
return (
@@ -156,6 +162,14 @@ function RootComponent() {
This Route Does Not Exist
+
+
+
+ {routerState().isLoading ? 'true' : 'false'}
+
+ {routerState().status}
+
+
This is an inline styled div
diff --git a/e2e/solid-start/basic/tests/redirect.spec.ts b/e2e/solid-start/basic/tests/redirect.spec.ts
index 2cad7d8f9d..2f6354aa81 100644
--- a/e2e/solid-start/basic/tests/redirect.spec.ts
+++ b/e2e/solid-start/basic/tests/redirect.spec.ts
@@ -1,5 +1,5 @@
import queryString from 'node:querystring'
-import { expect } from '@playwright/test'
+import { expect, type Page } from '@playwright/test'
import combinateImport from 'combinate'
import {
getDummyServerPort,
@@ -14,6 +14,19 @@ const combinate = (combinateImport as any).default as typeof combinateImport
const e2ePortKey = getE2EPortKey()
const PORT = await getTestServerPort(e2ePortKey)
const EXTERNAL_HOST_PORT = await getDummyServerPort(e2ePortKey)
+const POSTS_URL = `http://localhost:${PORT}/posts`
+
+async function waitForRouterIdle(page: Page) {
+ await expect(page.getByTestId('router-isLoading')).toHaveText('false')
+ await expect(page.getByTestId('router-status')).toHaveText('idle')
+}
+
+async function waitForPostsIndex(page: Page) {
+ await page.waitForURL(POSTS_URL)
+ expect(page.url()).toBe(POSTS_URL)
+ await waitForRouterIdle(page)
+ await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+}
test.describe('redirects', () => {
const internalNavigationTestMatrix = combinate({
@@ -34,7 +47,7 @@ test.describe('redirects', () => {
`via-${thrower}${reloadDocument ? '-reloadDocument' : ''}`,
)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
let requestHappened = false
const requestPromise = new Promise((resolve) => {
@@ -62,11 +75,7 @@ test.describe('redirects', () => {
await link.click()
- const url = `http://localhost:${PORT}/posts`
-
- await page.waitForURL(url)
- expect(page.url()).toBe(url)
- await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+ await waitForPostsIndex(page)
expect(fullPageLoad).toBe(reloadDocument)
})
},
@@ -83,12 +92,7 @@ test.describe('redirects', () => {
}) => {
await page.goto(`/redirect/internal/via-${thrower}`)
- const url = `http://localhost:${PORT}/posts`
-
- await page.waitForURL(url)
- expect(page.url()).toBe(url)
- await page.waitForLoadState('networkidle')
- await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+ await waitForPostsIndex(page)
})
})
@@ -107,7 +111,7 @@ test.describe('redirects', () => {
if (scenario === 'navigate') {
await page.goto(`/redirect/external?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const link = page.getByTestId(`via-${thrower}`)
await link.focus()
await link.click()
@@ -142,7 +146,7 @@ test.describe('redirects', () => {
if (scenario === 'navigate') {
await page.goto(`/redirect/${target}/serverFn?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const link = page.getByTestId(
`via-${thrower}${reloadDocument ? '-reloadDocument' : ''}`,
)
@@ -157,11 +161,12 @@ test.describe('redirects', () => {
const url =
target === 'internal'
- ? `http://localhost:${PORT}/posts`
+ ? POSTS_URL
: `http://localhost:${EXTERNAL_HOST_PORT}/`
await page.waitForURL(url)
expect(page.url()).toBe(url)
if (target === 'internal' && scenario === 'navigate') {
+ await waitForRouterIdle(page)
await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
expect(fullPageLoad).toBe(reloadDocument)
}
@@ -185,7 +190,7 @@ test.describe('redirects', () => {
await page.goto(`/redirect/${target}/serverFn/via-useServerFn?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const button = page.getByTestId('redirect-on-click')
@@ -198,11 +203,12 @@ test.describe('redirects', () => {
const url =
target === 'internal'
- ? `http://localhost:${PORT}/posts`
+ ? POSTS_URL
: `http://localhost:${EXTERNAL_HOST_PORT}/`
await page.waitForURL(url)
expect(page.url()).toBe(url)
if (target === 'internal') {
+ await waitForRouterIdle(page)
await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
expect(fullPageLoad).toBe(reloadDocument)
}
diff --git a/e2e/vue-start/basic/src/routes/__root.tsx b/e2e/vue-start/basic/src/routes/__root.tsx
index 8ebb8cec58..843ec05893 100644
--- a/e2e/vue-start/basic/src/routes/__root.tsx
+++ b/e2e/vue-start/basic/src/routes/__root.tsx
@@ -1,12 +1,14 @@
///
import {
Body,
+ ClientOnly,
HeadContent,
Html,
Link,
Outlet,
Scripts,
createRootRoute,
+ useRouterState,
} from '@tanstack/vue-router'
import { TanStackRouterDevtoolsInProd } from '@tanstack/vue-router-devtools'
@@ -66,6 +68,10 @@ export const Route = createRootRoute({
})
function RootComponent() {
+ const routerState = useRouterState({
+ select: (state) => ({ isLoading: state.isLoading, status: state.status }),
+ })
+
return (
@@ -156,6 +162,14 @@ function RootComponent() {
This Route Does Not Exist
+
+
+
+ {routerState.value.isLoading ? 'true' : 'false'}
+
+ {routerState.value.status}
+
+
This is an inline styled div
diff --git a/e2e/vue-start/basic/tests/redirect.spec.ts b/e2e/vue-start/basic/tests/redirect.spec.ts
index 2cad7d8f9d..2f6354aa81 100644
--- a/e2e/vue-start/basic/tests/redirect.spec.ts
+++ b/e2e/vue-start/basic/tests/redirect.spec.ts
@@ -1,5 +1,5 @@
import queryString from 'node:querystring'
-import { expect } from '@playwright/test'
+import { expect, type Page } from '@playwright/test'
import combinateImport from 'combinate'
import {
getDummyServerPort,
@@ -14,6 +14,19 @@ const combinate = (combinateImport as any).default as typeof combinateImport
const e2ePortKey = getE2EPortKey()
const PORT = await getTestServerPort(e2ePortKey)
const EXTERNAL_HOST_PORT = await getDummyServerPort(e2ePortKey)
+const POSTS_URL = `http://localhost:${PORT}/posts`
+
+async function waitForRouterIdle(page: Page) {
+ await expect(page.getByTestId('router-isLoading')).toHaveText('false')
+ await expect(page.getByTestId('router-status')).toHaveText('idle')
+}
+
+async function waitForPostsIndex(page: Page) {
+ await page.waitForURL(POSTS_URL)
+ expect(page.url()).toBe(POSTS_URL)
+ await waitForRouterIdle(page)
+ await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+}
test.describe('redirects', () => {
const internalNavigationTestMatrix = combinate({
@@ -34,7 +47,7 @@ test.describe('redirects', () => {
`via-${thrower}${reloadDocument ? '-reloadDocument' : ''}`,
)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
let requestHappened = false
const requestPromise = new Promise((resolve) => {
@@ -62,11 +75,7 @@ test.describe('redirects', () => {
await link.click()
- const url = `http://localhost:${PORT}/posts`
-
- await page.waitForURL(url)
- expect(page.url()).toBe(url)
- await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+ await waitForPostsIndex(page)
expect(fullPageLoad).toBe(reloadDocument)
})
},
@@ -83,12 +92,7 @@ test.describe('redirects', () => {
}) => {
await page.goto(`/redirect/internal/via-${thrower}`)
- const url = `http://localhost:${PORT}/posts`
-
- await page.waitForURL(url)
- expect(page.url()).toBe(url)
- await page.waitForLoadState('networkidle')
- await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
+ await waitForPostsIndex(page)
})
})
@@ -107,7 +111,7 @@ test.describe('redirects', () => {
if (scenario === 'navigate') {
await page.goto(`/redirect/external?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const link = page.getByTestId(`via-${thrower}`)
await link.focus()
await link.click()
@@ -142,7 +146,7 @@ test.describe('redirects', () => {
if (scenario === 'navigate') {
await page.goto(`/redirect/${target}/serverFn?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const link = page.getByTestId(
`via-${thrower}${reloadDocument ? '-reloadDocument' : ''}`,
)
@@ -157,11 +161,12 @@ test.describe('redirects', () => {
const url =
target === 'internal'
- ? `http://localhost:${PORT}/posts`
+ ? POSTS_URL
: `http://localhost:${EXTERNAL_HOST_PORT}/`
await page.waitForURL(url)
expect(page.url()).toBe(url)
if (target === 'internal' && scenario === 'navigate') {
+ await waitForRouterIdle(page)
await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
expect(fullPageLoad).toBe(reloadDocument)
}
@@ -185,7 +190,7 @@ test.describe('redirects', () => {
await page.goto(`/redirect/${target}/serverFn/via-useServerFn?${q}`)
- await page.waitForLoadState('networkidle')
+ await waitForRouterIdle(page)
const button = page.getByTestId('redirect-on-click')
@@ -198,11 +203,12 @@ test.describe('redirects', () => {
const url =
target === 'internal'
- ? `http://localhost:${PORT}/posts`
+ ? POSTS_URL
: `http://localhost:${EXTERNAL_HOST_PORT}/`
await page.waitForURL(url)
expect(page.url()).toBe(url)
if (target === 'internal') {
+ await waitForRouterIdle(page)
await expect(page.getByTestId('PostsIndexComponent')).toBeInViewport()
expect(fullPageLoad).toBe(reloadDocument)
}