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
25 changes: 25 additions & 0 deletions docs/start/framework/react/guide/execution-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,31 @@ function Analytics() {
}
```

#### useHydrated Hook

For more granular control over hydration-dependent behavior, use the `useHydrated` hook. It returns a boolean indicating whether the client has been hydrated:

```tsx
import { useHydrated } from '@tanstack/react-router'

function TimeZoneDisplay() {
const hydrated = useHydrated()
const timeZone = hydrated
? Intl.DateTimeFormat().resolvedOptions().timeZone
: 'UTC'

return <div>Your timezone: {timeZone}</div>
}
```

**Behavior:**

- **During SSR**: Always returns `false`
- **First client render**: Returns `false`
- **After hydration**: Returns `true` (and stays `true` for all subsequent renders)

This is useful when you need to conditionally render content based on client-side data (like browser timezone, locale, or localStorage) while providing a sensible fallback for server rendering.

### Environment-Specific Implementations

```tsx
Expand Down
24 changes: 24 additions & 0 deletions docs/start/framework/solid/guide/execution-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,30 @@ function Analytics() {
}
```

#### useHydrated Hook

For more granular control over hydration-dependent behavior, use the `useHydrated` hook. It returns an accessor (signal) indicating whether the client has been hydrated:

```tsx
import { useHydrated } from '@tanstack/solid-router'

function TimeZoneDisplay() {
const hydrated = useHydrated()
const timeZone = () =>
hydrated() ? Intl.DateTimeFormat().resolvedOptions().timeZone : 'UTC'

return <div>Your timezone: {timeZone()}</div>
}
```

**Behavior:**

- **During SSR**: Always returns `false`
- **First client render**: Returns `false`
- **After hydration**: Returns `true` (and stays `true` for all subsequent renders)

This is useful when you need to conditionally render content based on client-side data (like browser timezone, locale, or localStorage) while providing a sensible fallback for server rendering.

### Environment-Specific Implementations

```tsx
Expand Down
2 changes: 1 addition & 1 deletion packages/react-router/src/ClientOnly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function ClientOnly({ children, fallback = null }: ClientOnlyProps) {
/**
* Return a boolean indicating whether client hydration has occurred.
*/
function useHydrated(): boolean {
export function useHydrated(): boolean {
return React.useSyncExternalStore(
subscribe,
() => true,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-router/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export { useAwaited, Await } from './awaited'
export type { AwaitOptions } from './awaited'

export { CatchBoundary, ErrorComponent } from './CatchBoundary'
export { ClientOnly } from './ClientOnly'
export { ClientOnly, useHydrated } from './ClientOnly'

export {
FileRoute,
Expand Down
2 changes: 1 addition & 1 deletion packages/solid-router/src/ClientOnly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function ClientOnly(props: ClientOnlyProps) {
* ```
* @returns True if the JS has been hydrated already, false otherwise.
*/
function useHydrated(): Solid.Accessor<boolean> {
export function useHydrated(): Solid.Accessor<boolean> {
const [hydrated, setHydrated] = Solid.createSignal(false)
Solid.onMount(() => {
setHydrated(true)
Expand Down
2 changes: 1 addition & 1 deletion packages/solid-router/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export { useAwaited, Await } from './awaited'
export type { AwaitOptions } from './awaited'

export { CatchBoundary, ErrorComponent } from './CatchBoundary'
export { ClientOnly } from './ClientOnly'
export { ClientOnly, useHydrated } from './ClientOnly'

export {
FileRoute,
Expand Down