---
title: "@playstack/accounts-react"
description: "React account-list and active-account state for Playstack accounts."
tags: ["package","identity","accounts","react","pro"]
---

{/* package-access:start */}

> **Pro.** Covered by the Playstack Pro License. Registry access is required; check preview availability before installing. See [package access](/docs/packages#access-policy).

{/* package-access:end */}

`@playstack/accounts-react` exposes account selection state without merging account membership into the authentication client.

## Use it for

- Loading the accounts visible to the current user.
- Tracking the active account in React state.
- Switching account context through application-defined transport.
- Composing account-aware application shells.

## Install and compose

```sh
npm install @playstack/accounts @playstack/accounts-react react
```

Place the accounts provider inside the auth provider through a small application-owned bridge, so accounts stay optional and session replacement stays explicit:

```tsx
import { PlaystackAccountsProvider, createFetchAccountsClient } from '@playstack/accounts-react'
import { useAuth, useSession } from '@playstack/auth-react'

const accountsClient = createFetchAccountsClient({
  baseUrl: 'https://api.example.com',
  headers: () => ({ authorization: `Bearer ${transport.getAccessToken()}` }),
})

function AccountsBridge({ children }) {
  const { session } = useSession()
  const { replaceSession, refresh } = useAuth()
  return (
    <PlaystackAccountsProvider
      client={accountsClient}
      session={session}
      onSessionChange={usesBearerTransport ? refresh : replaceSession}
    >
      {children}
    </PlaystackAccountsProvider>
  )
}
```

With the same-origin cookie transport, `onSessionChange={replaceSession}` adopts the session the switch returned. With the split-origin bearer transport, the API rotated the refresh cookie when it issued the account-scoped session, so pass `refresh` instead and the transport obtains the access token that matches the new session.

```tsx
const { account, accounts, status, error, switchAccount, revalidate } = useAccount()
```

The provider clears account data when the authenticated user changes. Switching is allowed only to an account in the loaded list, and the returned session must match the same user, selected account, and listed role before state changes.

## Provider properties

| Property | Default | Purpose |
| --- | --- | --- |
| `client` | Required | `AccountsClient`: `listAccounts()` and `switchAccount(accountId)`. |
| `session` | Required | The current `AuthSessionView` or `null`, from `useSession()`. |
| `initialAccounts` | `undefined` | Pre-loaded account list; omit to fetch on mount. |
| `onSessionChange` | None | Receives the switched session; `replaceSession` or `refresh` from `useAuth()`. |
| `sessionParser` | Exact projection | Parser for sessions that carry validated `extensions`. |
| `onError` | None | Isolated error observer. |

## HTTP contract

The default client expects `GET /api/accounts` to return `{ accounts: AccountView[] }` (`id`, `name`, `slug`, `role`) and `POST /api/accounts/switch` to accept `{ accountId }` and return `{ session: AuthSessionView }`. Configure `baseUrl`, `accountsEndpoint`, `switchEndpoint`, `fetch` and a `headers` callback: echo the CSRF cookie for same-origin cookie sessions, or supply the transport's bearer token for split-origin sessions. Requests include cookies. Account and response objects reject unknown fields and duplicate IDs, and valid `{ error: { code, retryable, message } }` failures are preserved as `AccountsClientError.remote`.

Set `sessionParser` on both the client and the provider when sessions carry an application-validated `extensions` envelope; the default parser enforces the exact `AuthSessionView` projection and refuses extensions.

## Boundary

The package does not authorize membership and deliberately does not depend on `@playstack/auth-react`. Server operations still validate account scope and role on every request.

{/* package-reference:start */}

## API entry points and requirements

Reference snapshot: `@playstack/accounts-react@0.1.0-beta.1`. Import only the entry point your runtime needs. Paths below are relative to the installed package; use **Go to Definition** in your editor to inspect exact parameters, return types and overloads. Do not import the declaration-file paths directly.

| Public entry point | Declaration file |
| --- | --- |
| `@playstack/accounts-react` | `./dist/index.d.ts` |
| `@playstack/accounts-react/errors` | `./dist/errors.d.ts` |
| `@playstack/accounts-react/package.json` | No TypeScript declaration (asset or metadata export). |

Node.js engine requirement: `>=20`. This is not a claim that every entry point works in browsers or Workers.

### Peer dependencies

Keep existing framework versions that satisfy these ranges. Install optional peers only when using the corresponding adapter. The package manager resolves ordinary dependencies separately.

| Peer | Compatible range | When needed |
| --- | --- | --- |
| `@playstack/accounts` | `0.1.0-beta.1` | Required by the package. |
| `@playstack/auth` | `0.1.0-beta.1` | Required by the package. |
| `@playstack/core` | `0.1.0-beta.1` | Required by the package. |
| `react` | `^18.2.0 \|\| ^19.0.0` | Required by the package. |

For a complete first program, start with [Getting started](/docs/getting-started). For API lookup and partial-example conventions, see [Reading the reference](/docs/packages#reading-the-reference). Provider failures, lifecycle requirements and application responsibilities remain described in the guide above; types alone do not establish production safety.

{/* package-reference:end */}
