# useClient

> **useClient**(): [`Client`](https://ic-reactor.b3pay.net/v4/libs/interfaces/client/)

Defined in: [react/src/index.tsx:528](https://github.com/B3Pay/ic-reactor/blob/6b3b9f58b7868082175216ca6e3688d278d17c1f/packages/react/src/index.tsx#L528)

The client of the nearest [ReactorProvider](https://ic-reactor.b3pay.net/v4/libs/functions/reactorprovider/): the one object that
builds canister handles and query options, and that signs users in and out.

Call it in the body of each component that builds keys or options, on
every render, and build them from what it returns there, never from a
client held at module scope: they are built for the caller this render
shows. Do not keep what it returns past the render: while a page hydrates
it is a view for the anonymous caller, and a view never moves on. An effect
or a callback that uses it closes over its render's value and lists it in
its dependencies (`react-hooks/exhaustive-deps`), so that it runs again with
the client after hydrating. Kept from the hydrating render anywhere else
(`useState(client)`, `useRef(client)`, a `useMemo` or `useCallback` with
`[]`, a module variable), it stays that view: the component shows the
anonymous caller's data, a read it starts while the user is signed in is
cancelled, and a write through it still signs as the live caller. Nothing
warns about it. A nested [ReactorProvider](https://ic-reactor.b3pay.net/v4/libs/functions/reactorprovider/) given it
(`client={() => client}`) holds the client the view was made over.
It follows the client's caller with `useSyncExternalStore`, so a
component that calls it renders again when the caller changes (a sign-in, a
switch of account, a sign-out) and never otherwise: a change of status that
leaves the caller as it is (a session that expired, or one signed in
elsewhere, both call as the anonymous principal) renders nothing. In the
steady state it returns the provider's client object itself.

On a server, and while a page hydrates, the caller is the anonymous one, as
for [useAuth](https://ic-reactor.b3pay.net/v4/libs/functions/useauth/). In a browser that holds a session, the hydrating render
gets a view of the client for the anonymous caller: its `queryKey`,
`queryOptions`, `caller()` and `authState()` are the anonymous caller's, so
the page finds what the server prefetched and dehydrated and matches its
HTML; everything else (canisters, `mutationOptions`, `signIn`, `signOut`,
the `QueryClient`) is the client's own, and a write signs as the caller
current when it runs. Right after hydrating, React renders the component
again with the client itself, for the user: a read with none of the user's
data yet shows its loading state, and a `useSuspenseQuery` read its
boundary's fallback, until that data arrives. A client built with
`identity` keeps its caller for good and is always returned as it is.

Three consequences of that move on a signed-in reload:

- A Suspense boundary that is still dehydrated below a component that
  renders with the caller (this hook or [useAuth](https://ic-reactor.b3pay.net/v4/libs/functions/useauth/)), because its lazy
  code is still loading or its streamed HTML has not arrived, is rendered
  on the client when that component moves on: it shows its fallback
  instead of the server's HTML, and React 18 reports a recoverable error.
  Its data is still the user's. A `useAuth()` component also moves on in a
  tab whose session expired or is signed in elsewhere. Render such a boundary where no component
  that renders with the caller sits above it, or pass it in as `children`,
  which a component's own update does not render again.
- A read the hydrating render built may still run once (TanStack Query
  refetches stale data on mount, and an effect may fetch with the view's
  options). It is cancelled before anything is sent. A key that holds data
  keeps it as it was, and a fetch of it resolves with that data. A key with
  none fails (`kind` `"cancelled"`, `code` `"caller_changed"`) until the
  anonymous caller is current again: the hydrating render's own reads never
  show that, but a listener of
  `client.queryClient.getQueryCache().subscribe()` (the client takes no
  `QueryCache` of yours), an effect that awaits the fetch and, for a
  `useSuspenseQuery` read the server rendered without dehydrating its
  data, React's `onRecoverableError` (as the reported error's `cause` on
  React 19) see it, so ignore `kind` `"cancelled"` there.
- Put a Suspense boundary above every component that reads with
  `useSuspenseQuery`, on React 18 and 19 alike. The move is a synchronous
  update, which such a read suspends until the user's data arrives. With a
  boundary above, the boundary shows its fallback, then the user's data,
  and the rest of the page responds meanwhile. With none, React 18 refuses
  the update ("A component suspended while responding to synchronous
  input") and unmounts the root, so a signed-in reload renders nothing.
  React 19 keeps the server's HTML on screen, but until the user's data
  arrives, however long the read and its retries take, a click or any other
  update outside a transition commits nothing, and neither does a
  transition that renders the reading component again.

## Returns

[`Client`](https://ic-reactor.b3pay.net/v4/libs/interfaces/client/)

## Throws

Error outside a `ReactorProvider`, naming it.