Overview
useAccounts returns the list of all stored accounts and the currently active account. Use it to render an account switcher or display the signed-in user’s identity.
Usage Example
Returns
StoredAccount[]
Array of all stored accounts, derived from the accounts map in Redux state.
Each one carries the profile summary, the two credential markers below, and
the
needsPushRebind notification marker.StoredAccount | null
The account currently selected, or
null when nothing is selected.Selection and session are not the same thing, and the gap between them is a
state your UI has to render. An account can be selected with no live session
behind it — during an addAccount() flow, or
after a sign-in was refused at the account limit. Read accessToken from
useAuth for whether a session exists; read this for
whose account the app is pointed at.number
Total number of stored accounts.
boolean
true when there is no active account because the user deliberately signed
out — or removed the active account, deleted it, or had a stored credential
refused at launch — as opposed to “nothing has ever been selected”. Both look like activeAccount === null; this is what
tells them apart, and it is persisted, so it survives a relaunch.A launch that could not reach the server does not set it: the stored account
stays selected and its session is restored later. Only a refusal counts.While it is true, the SDK will not auto-select a stored account at launch.
It clears as soon as any account is successfully activated.boolean
true when an account was actually refused admission because the map was
already at the 5-account limit. Clears on the next successful admission and
on any removal. See useAddAccount for how it
differs from canAddAccount and from
wouldExceedAccountLimit.Render off it — do not read it eagerly. The clear is dispatched from an
effect, so it lands one render after a successful admission rather than
synchronously inside the call that caused it. Reading it immediately after
awaiting a sign-in returns the value from before that effect flushed, which
may be a true left over from an earlier, unrelated refusal. See
When accountLimitReached clears.StoredAccount Type
StoredAccount is a superset of the AccountSummary shape stored in the
account map, so code that only reads id/name/username/email/avatar is
unaffected.
Telling a Live Account From a Dead One
A stored account can stop working while it is sitting in the switcher. Two fields let you show that before the user taps it, and you need both — neither is sufficient on its own:number
Proactive. Read from the stored refresh token’s own
exp claim when the
entry is written (a decode, never a verification and never a network call).0 means unknown — the token carried no readable numeric exp, so the SDK
recorded nothing rather than guessing. It sorts as already-expired
deliberately: treating a credential the SDK cannot read as fresh is the worse
failure.boolean
Reactive. Set when a transition into this account is refused — by a switch,
or by the automatic restore at app launch, which is the most common way a
revoked credential is discovered. Cleared the moment the account is
successfully activated again, whether by a switch that works or by signing
into it afresh.This catches every death
tokenExpiresAt cannot see: reuse detection, a
password change, a remote sign-out-all, an admin revocation. All of those
destroy the token family while exp is still comfortably in the future. It is
also set without any network call when the stored entry carries no usable
credential at all, which is the same conclusion reached sooner.A failed switch that could not reach the server does not set it — a flaky
network is not a dead account. AccountTransitionError.credentialRejected is
the same distinction, reported to the caller at the moment of failure; see
useSwitchAccount.Notifications paused: needsPushRebind
boolean
true when this account’s push binding points at a device token this device no
longer holds, because the token rotated while the account was in the
background.Its credential is fine and its data is fine — only the notification routing is
stale. Switching into the account re-creates the binding and clears this, so
the useful thing to render is an invitation to open it rather than a sign-in
prompt: “Notifications paused — open to resume.”Only ever raised for accounts that explicitly enabled push on this device. An
account that never asked for notifications has none to pause.needsReauth. They mean opposite things about the
account’s health, and saying the wrong one is wrong in both directions: telling
a user to sign in again when their notifications are merely stale asks for a
password they do not need, and treating a paused account as fine hides the one
thing a tap would fix.
Neither credential marker is a promise: needsReauth: false with a future
tokenExpiresAt means nothing has gone wrong that the SDK knows of, not that
the next switch is guaranteed to succeed. A switch can still fail, and when it
does the current session is left untouched — see
When a transition fails.
On Expo, avatar and then email may be dropped from a stored entry if it
would otherwise exceed SecureStore’s per-value limit. id, name, username,
the credential and the markers are never dropped. See
Where accounts are stored.
Rendering the Signed-Out State
No account is auto-selected after a sign-out, removal or deletion, soactiveAccount can be null while accounts is non-empty. That is the account-picker state:
accessToken, not on activeAccount. A selection is not a session:
addAccount() leaves the previous account selected while it clears the session,
so a selection-based gate would render your app for an account that has no
tokens behind it. signedOut then separates the picker state from a device
where nobody has ever signed in.

