---
id: "packages/active-ui/client-only"
title: "ClientOnly"
description: "Renders its content only in the browser, after hydration, and a fallback on the server."
url: "/packages/active-ui/client-only"
locale: "en"
revision: "fa4bfd24c0a45a93"
---

# ClientOnly

`ClientOnly` renders its children only in the browser, after hydration; on the server and during
hydration it renders `fallback`. Use it for content that differs between server and browser, such
as the reader's time zone or a browser API, so React does not report a hydration mismatch.

**Example: What only the browser knows**

Client: Runs entirely in your browser. Source: `examples/ui/client-only.tsx`.

```tsx
// apps/docs/examples/ui/client-only.tsx
'use client';

import {ClientOnly} from '@workspace/active-ui/components/composed/client-only';

/**
 * Reads browser APIs while it renders. As its own component it renders only
 * inside `ClientOnly`: an expression such as `{window.innerWidth}` written
 * directly as a child would run on the server too.
 */
function BrowserFacts() {
  return (
    <>
      <strong>{Intl.DateTimeFormat().resolvedOptions().timeZone}</strong>,
      window width {window.innerWidth} px
    </>
  );
}

/**
 * Content that only the browser knows: your time zone and window width. The
 * server renders the fallback, and the browser replaces it after hydration,
 * without a mismatch.
 */
export default function ClientOnlyExample() {
  return (
    <p className="text-sm">
      Your browser&apos;s time zone:{' '}
      <ClientOnly fallback={<span className="text-muted-foreground">-</span>}>
        <BrowserFacts />
      </ClientOnly>
    </p>
  );
}
```

## What the composition adds

It uses [`useIsClient`](/packages/active-ui/hooks), built on `useSyncExternalStore`: `false` on the
server and during hydration, `true` after it.

## The children run on the server too

React evaluates the children where `ClientOnly` is written, before `ClientOnly` decides what to
render. An expression such as `{window.innerWidth}` as a child therefore runs on the server and
fails there. Put code that reads a browser API in a component of its own, as `BrowserFacts` in the
example, and render that component inside `ClientOnly`.

## Usage

```tsx
import {ClientOnly} from '@workspace/active-ui/components/composed/client-only';

<ClientOnly fallback="-">{formatDateTime(createdAt, presentation)}</ClientOnly>;
```

## What your application provides

- A fallback with the same size as the content where a jump in the layout would disturb.
- Content that can render on the server stays outside: everything inside appears only after
  hydration, and search engines and readers without JavaScript see the fallback.

## API

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | yes | Content to render on the client |
| `fallback` | `ReactNode` | no | Fallback content during SSR and hydration (default: null) |
