diff --git a/e2e/react-start/basic/src/routes/specialChars/hash.tsx b/e2e/react-start/basic/src/routes/specialChars/hash.tsx index 1f1227e020..355ad4963c 100644 --- a/e2e/react-start/basic/src/routes/specialChars/hash.tsx +++ b/e2e/react-start/basic/src/routes/specialChars/hash.tsx @@ -1,4 +1,5 @@ import { createFileRoute, useLocation } from '@tanstack/react-router' +import { useState } from 'react' export const Route = createFileRoute('/specialChars/hash')({ component: RouteComponent, @@ -6,10 +7,26 @@ export const Route = createFileRoute('/specialChars/hash')({ function RouteComponent() { const l = useLocation() + const [toggleHashValue, setToggleHashValue] = useState(false) return (
- Hello "/specialChars/hash"! - {l.hash} +
Hello "/specialChars/hash"!
+ +
+ {toggleHashValue && ( +
+ Hash Value{l.hash} +
+ )} +
) } diff --git a/e2e/react-start/basic/src/routes/specialChars/route.tsx b/e2e/react-start/basic/src/routes/specialChars/route.tsx index 4e75790ddd..b15a363166 100644 --- a/e2e/react-start/basic/src/routes/specialChars/route.tsx +++ b/e2e/react-start/basic/src/routes/specialChars/route.tsx @@ -46,9 +46,22 @@ function RouteComponent() { className: 'font-bold', }} hash={'대|'} - data-testid="special-hash-link" + data-testid="special-hash-link-1" > - Unicode Hash + Unicode Hash 대| + {' '} + + Unicode Hash abc {' '} { page, baseURL, }) => { - await expect(page.getByTestId('special-hash-link')).not.toHaveClass( + await expect(page.getByTestId('special-hash-link-1')).not.toContainClass( 'font-bold', ) + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( + 'font-bold', + ) + await page.goto('/specialChars/hash#대|') await page.waitForURL(`${baseURL}/specialChars/hash#%EB%8C%80|`) @@ -118,11 +122,18 @@ test.describe('Unicode route rendering', () => { await expect(page.getByTestId('special-hash-heading')).toBeInViewport() - const hashValue = await page.getByTestId('special-hash').textContent() + await expect(page.getByTestId('special-hash-link-1')).toContainClass( + 'font-bold', + ) - await expect(page.getByTestId('special-hash-link')).toHaveClass( + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( 'font-bold', ) + + await page.getByTestId('toggle-hash-button').click() + + const hashValue = await page.getByTestId('special-hash').textContent() + expect(hashValue).toBe('대|') }) @@ -130,10 +141,15 @@ test.describe('Unicode route rendering', () => { page, baseURL, }) => { - await expect(page.getByTestId('special-hash-link')).not.toHaveClass( + await expect(page.getByTestId('special-hash-link-1')).not.toContainClass( 'font-bold', ) - const link = page.getByTestId('special-hash-link') + + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( + 'font-bold', + ) + + const link = page.getByTestId('special-hash-link-1') await link.click() @@ -142,11 +158,18 @@ test.describe('Unicode route rendering', () => { await expect(page.getByTestId('special-hash-heading')).toBeInViewport() - const hashValue = await page.getByTestId('special-hash').textContent() + await expect(page.getByTestId('special-hash-link-1')).toContainClass( + 'font-bold', + ) - await expect(page.getByTestId('special-hash-link')).toHaveClass( + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( 'font-bold', ) + + await page.getByTestId('toggle-hash-button').click() + + const hashValue = await page.getByTestId('special-hash').textContent() + expect(hashValue).toBe('대|') }) }) diff --git a/e2e/solid-start/basic/src/routes/specialChars/hash.tsx b/e2e/solid-start/basic/src/routes/specialChars/hash.tsx index 43d24ada29..391ec1a72d 100644 --- a/e2e/solid-start/basic/src/routes/specialChars/hash.tsx +++ b/e2e/solid-start/basic/src/routes/specialChars/hash.tsx @@ -1,5 +1,5 @@ import { createFileRoute, useLocation } from '@tanstack/solid-router' -import { createEffect, createSignal } from 'solid-js' +import { createSignal } from 'solid-js' export const Route = createFileRoute('/specialChars/hash')({ component: RouteComponent, @@ -7,16 +7,27 @@ export const Route = createFileRoute('/specialChars/hash')({ function RouteComponent() { const location = useLocation() - const [getHash, setHash] = createSignal('') - - createEffect(() => { - setHash(location().hash) - }) + const [toggleHashValue, setToggleHashValue] = createSignal(false) return (
- Hello "/specialChars/hash"! - {getHash()} +
Hello "/specialChars/hash"!
+ +
+ {toggleHashValue() && ( +
+ Hash Value{location().hash} +
+ )} +
) } diff --git a/e2e/solid-start/basic/src/routes/specialChars/route.tsx b/e2e/solid-start/basic/src/routes/specialChars/route.tsx index 863cb79506..e69155da67 100644 --- a/e2e/solid-start/basic/src/routes/specialChars/route.tsx +++ b/e2e/solid-start/basic/src/routes/specialChars/route.tsx @@ -46,10 +46,23 @@ function RouteComponent() { class: 'font-bold', }} hash={'대|'} - data-testid="special-hash-link" + data-testid="special-hash-link-1" > Unicode Hash {' '} + + Unicode Hash abc + {' '} { page, baseURL, }) => { - await expect(page.getByTestId('special-hash-link')).not.toHaveClass( + await expect(page.getByTestId('special-hash-link-1')).not.toContainClass( 'font-bold', ) + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( + 'font-bold', + ) + await page.goto('/specialChars/hash#대|') await page.waitForURL(`${baseURL}/specialChars/hash#%EB%8C%80|`) @@ -118,13 +122,18 @@ test.describe('Unicode route rendering', () => { await expect(page.getByTestId('special-hash-heading')).toBeInViewport() - const hashValue = await page.getByTestId('special-hash').textContent() + // TODO: this should work but seems to be a bug in reactivity on Solid Dynamic component. Still investigating. + // await expect(page.getByTestId('special-hash-link-1')).toContainClass( + // 'font-bold', + // ) + + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( + 'font-bold', + ) - const el = await page - .getByTestId('special-hash-link') - .evaluate((e) => e.classList.value) + await page.getByTestId('toggle-hash-button').click() - expect(el).toContain('font-bold') + const hashValue = await page.getByTestId('special-hash').textContent() expect(hashValue).toBe('대|') }) @@ -133,10 +142,15 @@ test.describe('Unicode route rendering', () => { page, baseURL, }) => { - await expect(page.getByTestId('special-hash-link')).not.toHaveClass( + await expect(page.getByTestId('special-hash-link-1')).not.toContainClass( 'font-bold', ) - const link = page.getByTestId('special-hash-link') + + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( + 'font-bold', + ) + + const link = page.getByTestId('special-hash-link-1') await link.click() @@ -145,11 +159,18 @@ test.describe('Unicode route rendering', () => { await expect(page.getByTestId('special-hash-heading')).toBeInViewport() - const hashValue = await page.getByTestId('special-hash').textContent() + await expect(page.getByTestId('special-hash-link-1')).toContainClass( + 'font-bold', + ) - await expect(page.getByTestId('special-hash-link')).toHaveClass( + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( 'font-bold', ) + + await page.getByTestId('toggle-hash-button').click() + + const hashValue = await page.getByTestId('special-hash').textContent() + expect(hashValue).toBe('대|') }) }) diff --git a/e2e/vue-start/basic/src/routes/specialChars/hash.tsx b/e2e/vue-start/basic/src/routes/specialChars/hash.tsx index 1f76f5c7bb..d1cb9041ef 100644 --- a/e2e/vue-start/basic/src/routes/specialChars/hash.tsx +++ b/e2e/vue-start/basic/src/routes/specialChars/hash.tsx @@ -1,15 +1,39 @@ import { createFileRoute, useLocation } from '@tanstack/vue-router' +import { defineComponent, ref } from 'vue' + +const RouteComponent = defineComponent({ + setup() { + const l = useLocation() + const toggleHashValue = ref(false) + + const toggle = () => { + toggleHashValue.value = !toggleHashValue.value + } + + return () => ( +
+
Hello "/specialChars/hash"!
+ +
+ {toggleHashValue.value && ( +
+ Hash Value{l.value.hash} +
+ )} +
+
+ ) + }, +}) export const Route = createFileRoute('/specialChars/hash')({ component: RouteComponent, }) - -function RouteComponent() { - const l = useLocation() - return ( -
- Hello "/specialChars/hash"! - {l.value.hash} -
- ) -} diff --git a/e2e/vue-start/basic/src/routes/specialChars/route.tsx b/e2e/vue-start/basic/src/routes/specialChars/route.tsx index b0366b65f6..86dc29d39a 100644 --- a/e2e/vue-start/basic/src/routes/specialChars/route.tsx +++ b/e2e/vue-start/basic/src/routes/specialChars/route.tsx @@ -46,10 +46,23 @@ function RouteComponent() { class: 'font-bold', }} hash={'대|'} - data-testid="special-hash-link" + data-testid="special-hash-link-1" > Unicode Hash {' '} + + Unicode Hash abc + {' '} { page, baseURL, }) => { - await expect(page.getByTestId('special-hash-link')).not.toHaveClass( + await expect(page.getByTestId('special-hash-link-1')).not.toContainClass( 'font-bold', ) + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( + 'font-bold', + ) + await page.goto('/specialChars/hash#대|') await page.waitForURL(`${baseURL}/specialChars/hash#%EB%8C%80|`) @@ -118,11 +122,18 @@ test.describe('Unicode route rendering', () => { await expect(page.getByTestId('special-hash-heading')).toBeInViewport() - const hashValue = await page.getByTestId('special-hash').textContent() + await expect(page.getByTestId('special-hash-link-1')).toContainClass( + 'font-bold', + ) - await expect(page.getByTestId('special-hash-link')).toHaveClass( + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( 'font-bold', ) + + await page.getByTestId('toggle-hash-button').click() + + const hashValue = await page.getByTestId('special-hash').textContent() + expect(hashValue).toBe('대|') }) @@ -130,10 +141,15 @@ test.describe('Unicode route rendering', () => { page, baseURL, }) => { - await expect(page.getByTestId('special-hash-link')).not.toHaveClass( + await expect(page.getByTestId('special-hash-link-1')).not.toContainClass( 'font-bold', ) - const link = page.getByTestId('special-hash-link') + + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( + 'font-bold', + ) + + const link = page.getByTestId('special-hash-link-1') await link.click() @@ -142,11 +158,18 @@ test.describe('Unicode route rendering', () => { await expect(page.getByTestId('special-hash-heading')).toBeInViewport() - const hashValue = await page.getByTestId('special-hash').textContent() + await expect(page.getByTestId('special-hash-link-1')).toContainClass( + 'font-bold', + ) - await expect(page.getByTestId('special-hash-link')).toHaveClass( + await expect(page.getByTestId('special-hash-link-2')).not.toContainClass( 'font-bold', ) + + await page.getByTestId('toggle-hash-button').click() + + const hashValue = await page.getByTestId('special-hash').textContent() + expect(hashValue).toBe('대|') }) }) diff --git a/packages/react-router/src/link.tsx b/packages/react-router/src/link.tsx index 72e95df0e9..31088ede19 100644 --- a/packages/react-router/src/link.tsx +++ b/packages/react-router/src/link.tsx @@ -13,6 +13,7 @@ import { useRouter } from './useRouter' import { useForwardedRef, useIntersectionObserver } from './utils' +import { useHydrated } from './ClientOnly' import type { AnyRouter, Constrain, @@ -52,6 +53,7 @@ export function useLinkProps< const [isTransitioning, setIsTransitioning] = React.useState(false) const hasRenderFetched = React.useRef(false) const innerRef = useForwardedRef(forwardedRef) + const isHydrated = useHydrated() const { // custom props @@ -225,7 +227,7 @@ export function useLinkProps< } if (activeOptions?.includeHash) { - return s.location.hash === next.hash + return isHydrated && s.location.hash === next.hash } return true }, diff --git a/packages/solid-router/src/link.tsx b/packages/solid-router/src/link.tsx index fb1ec6e3c2..04ddc65596 100644 --- a/packages/solid-router/src/link.tsx +++ b/packages/solid-router/src/link.tsx @@ -230,8 +230,7 @@ export function useLinkProps< } } - // url hash is not available on server, so do not evaluate this here when on server - if (local.activeOptions?.includeHash && !router.isServer) { + if (local.activeOptions?.includeHash) { return s.location.hash === next().hash } return true