> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# React Hooks

> Reactive bindings for the Dynamic JavaScript SDK — useUser, useGetWalletAccounts, useOnEvent, and more.

`@dynamic-labs-sdk/react-hooks` is a thin React layer over [`@dynamic-labs-sdk/client`](/javascript/reference/client/create-dynamic-client). It exposes a `<DynamicProvider>` and a set of hooks that subscribe to client state and re-render your components when that state changes.

<Warning>
  The JavaScript SDK is headless — there is no built-in modal, wallet picker, or
  login form. You build all UI yourself. See the [JavaScript SDK
  Overview](/javascript/overview) for details.
</Warning>

<Note>
  New to the hooks? Read [How React Hooks
  Work](/javascript/reference/react-hooks-guide) first — it covers the naming
  rule (each client function maps to a same-named `use` hook), which functions
  get a hook, and the three shapes a hook can take (query, mutation, state).
  This page is the reference for setup and the headline state hooks.
</Note>

## Installation

```bash theme={"system"}
npm i @dynamic-labs-sdk/react-hooks
```

The package has `@dynamic-labs-sdk/client` and `react` as peer dependencies.

## Setup

Wrap your app in `DynamicProvider` and pass the client instance you created with [`createDynamicClient`](/javascript/reference/client/create-dynamic-client):

```tsx theme={"system"}
import { DynamicProvider } from '@dynamic-labs-sdk/react-hooks';
import { dynamicClient } from './dynamicClient';

function App() {
  return (
    <DynamicProvider client={dynamicClient}>
      <YourApp />
    </DynamicProvider>
  );
}
```

Any hook used outside a `DynamicProvider` throws `MissingProviderError`.

## State hooks

These hooks read directly from the client and re-render the component when the underlying state changes. Like all hooks in this package, they return the full TanStack Query result (`{ data, isLoading, error, refetch, … }`). They have no parameters.

Each state hook returns the full react-query result — `{ data, isLoading, error, refetch, ... }` — so the value you want lives on `data`. Destructure it: `const { data: user } = useUser()`. The descriptions below refer to what `data` holds.

### `useUser`

`data` is the current authenticated user, or `null` if no user is signed in. Re-renders on sign-in, sign-out, and profile updates.

```tsx theme={"system"}
import { useUser } from '@dynamic-labs-sdk/react-hooks';

function ProfileBadge() {
  const { data: user } = useUser();
  if (!user) return <SignInButton />;
  return <span>{user.email ?? user.firstName}</span>;
}
```

### `useGetWalletAccounts`

Returns all wallet accounts on the current session, verified and unverified. Re-renders when accounts are added, removed, or verified.

```tsx theme={"system"}
import { useGetWalletAccounts } from '@dynamic-labs-sdk/react-hooks';

function WalletList() {
  const { data: walletAccounts = [] } = useGetWalletAccounts();
  return (
    <ul>
      {walletAccounts.map((account) => (
        <li key={account.id}>
          {account.chain}: {account.address}
        </li>
      ))}
    </ul>
  );
}
```

### `useGetUserSocialAccounts`

Returns the user's linked social accounts (`SocialAccount[]`). Re-renders when the user changes. Empty array when no user is signed in.

```tsx theme={"system"}
import { useGetUserSocialAccounts } from '@dynamic-labs-sdk/react-hooks';

function LinkedSocials() {
  const { data: accounts = [] } = useGetUserSocialAccounts();
  return accounts.map((account) => (
    <div key={account.verifiedCredentialId}>
      {account.provider}: {account.displayName ?? account.emails[0]}
    </div>
  ));
}
```

See [Social Account Linking](/javascript/authentication-methods/social-linking) for the management APIs.

### `useGetAvailableWalletProvidersData`

Returns the wallet providers available to connect and their metadata (`WalletProviderData[]`). Re-renders when the available providers change (for example on a network switch).

```tsx theme={"system"}
import { useGetAvailableWalletProvidersData } from '@dynamic-labs-sdk/react-hooks';

function AvailableWallets() {
  const { data: providers = [] } = useGetAvailableWalletProvidersData();
  return providers.map((provider) => (
    <button key={provider.key}>Connect {provider.metadata.name}</button>
  ));
}
```

### `useInitStatus`

Returns the client's initialization status: `'uninitialized' | 'in-progress' | 'finished' | 'failed'`. Use this to gate UI that depends on SDK methods until the client is ready.

```tsx theme={"system"}
import { useInitStatus } from '@dynamic-labs-sdk/react-hooks';

function Bootstrap({ children }) {
  const { data: initStatus } = useInitStatus();
  if (initStatus !== 'finished') return <Splash />;
  return children;
}
```

See [Initializing the Dynamic Client](/javascript/reference/client/initialize-dynamic-client) for init-status semantics.

### `useSessionExpiresAt`

Returns the session expiration `Date`, or `null` if there is no active session. Re-renders on session updates.

```tsx theme={"system"}
import { useSessionExpiresAt } from '@dynamic-labs-sdk/react-hooks';

function SessionCountdown() {
  const { data: expiresAt } = useSessionExpiresAt();
  if (!expiresAt) return null;
  return <span>Session ends at {expiresAt.toLocaleTimeString()}</span>;
}
```

## Event hook

### `useOnEvent`

Subscribes to any client event for the lifetime of the component. The subscription is cleaned up on unmount or when the `event` name changes. The listener is wrapped in a ref, so updating its identity between renders does not re-subscribe.

```tsx theme={"system"}
import { useOnEvent } from '@dynamic-labs-sdk/react-hooks';

function LogoutLogger() {
  useOnEvent({
    event: 'logout',
    listener: ({ reason } = {}) => {
      console.log('Logged out:', reason);
    },
  });
  return null;
}
```

The listener signature is inferred from the event name. See the [Events Catalog](/javascript/reference/client/events-catalog) for the full event surface.

For state-change events (`userChanged`, `walletAccountsChanged`, `tokenChanged`, etc.) prefer the dedicated state hooks above — they subscribe for you and avoid manual subscription bookkeeping.

## Client access

### `useDynamicClient`

Returns the `DynamicClient` instance from context. Throws `MissingProviderError` if used outside a `DynamicProvider`. Most code should not need this — use the state hooks for reactive state, and import client functions directly (`signMessage`, `getMultichainTokenBalances`, etc.) for one-shot calls.

```tsx theme={"system"}
import { useDynamicClient } from '@dynamic-labs-sdk/react-hooks';

function ClientDebugger() {
  const client = useDynamicClient();
  return <pre>{JSON.stringify(client.initStatus, null, 2)}</pre>;
}
```

## Multiple clients

If your app uses more than one Dynamic client, mount a separate `DynamicProvider` for each subtree. Hooks resolve the closest provider, so state from one client never leaks into a tree wrapped in a different one.

## Related

* [React Hooks Catalog](/javascript/reference/react-hooks-catalog) — complete reference for all 87 hooks, organized by category
* [How React Hooks Work](/javascript/reference/react-hooks-guide) — naming rule, shapes, when to use a hook vs. a direct call
* [React Quickstart (JS SDK)](/javascript/reference/react-quickstart)
* [Create a Dynamic Client](/javascript/reference/client/create-dynamic-client)
* [Initializing the Dynamic Client](/javascript/reference/client/initialize-dynamic-client)
* [Events Catalog](/javascript/reference/client/events-catalog)
* [Subscribe to client events](/javascript/reference/client/on-event)
