# useMounted

A hook that reports whether the component has mounted on the client.

## Installation

```bash
npx shadcn@latest add https://mwui.vercel.app/r/use-mounted.json
```

[Registry JSON](https://mwui.vercel.app/r/use-mounted.json)

## Preview

```tsx
import * as React from "react";

import { Skeleton } from "@/components/ui/skeleton";

import { useMounted } from "@/hooks/use-mounted";

export function Preview() {
  const mounted = useMounted();
  const [now] = React.useState(() => new Date());

  return (
    <div className="flex w-full max-w-sm flex-col gap-3 text-sm">
      <div className="flex items-center justify-between rounded-lg border border-border px-3 py-2">
        <span className="text-muted-foreground">Local time</span>
        {mounted ? (
          <span className="font-mono tabular-nums">{now.toLocaleTimeString()}</span>
        ) : (
          <Skeleton className="h-4 w-20" />
        )}
      </div>

      <p className="text-xs text-muted-foreground">
        The server has no timezone for this user, so the formatted time renders only after
        hydration.
      </p>
    </div>
  );
}
```


## Source

### hooks/use-mounted.ts

```ts
"use client";

import * as React from "react";

function subscribe(): () => void {
  return () => {};
}

function getSnapshot(): boolean {
  return true;
}

function getServerSnapshot(): boolean {
  return false;
}

function useMounted(): boolean {
  return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
}

export { useMounted };
```



## Usage

For the handful of values that genuinely cannot match between server and client — a locale-formatted
date, a resolved theme, a portal target, anything read from `window` — render a stable placeholder
until after hydration.

```tsx
import { useMounted } from "@/hooks/use-mounted";

function LocalTime({ date }: { date: Date }) {
  const mounted = useMounted();

  if (!mounted) return <span className="opacity-0">00:00</span>;

  return <span>{date.toLocaleTimeString()}</span>;
}
```

## Why `useSyncExternalStore`

The usual implementation is `useState(false)` plus an effect that sets it to `true`. That works, but
it schedules an extra state update on every mounted component and is easy to accidentally call
during a render that React may discard.

`useSyncExternalStore` expresses the same thing declaratively: the server snapshot is `false`, the
client snapshot is `true`, and the store never notifies. React reads `false` while rendering on the
server and during hydration, then `true` — no effect, no extra state.

## Use it sparingly

Every `useMounted` branch is content the user does not see on first paint, and it is not the fix for
most hydration warnings. Reach for it when the value is genuinely client-only. When the difference
is only visual, prefer CSS; when it is data, prefer passing it down from the server.

