Firebase Hooksv0.3.0

HookResult

The shape every action resolves to.

Every action in this package resolves to a HookResult. Actions never throw.

type HookResult<T> =
  | ({ success: true } & T)
  | { success: false; error: string; code: string | null; cause: unknown };
import type { HookResult } from '@timonwa/firebase-hooks';

On success

success: true plus whatever that action returns. Sign-ins add user and credential, where credential is Firebase's raw UserCredential — nothing is withheld or reshaped.

const result = await login(email, password);
if (result.success) {
  result.user; // User
  result.credential; // UserCredential
}

Actions with nothing to return resolve to plain { success: true }.

On failure

FieldTypeWhat it is
errorstringThe message for rendering — raw by default
codestring | nullFirebase's own code, e.g. "auth/invalid-credential"
causeunknownThe complete untouched error

code and cause are always Firebase's own. Only error is ever processed, and only if you opt in — see Error handling.

Narrowing

success is a discriminant, so TypeScript narrows on it:

const result = await login(email, password);
if (!result.success) {
  result.code; // string | null
  return;
}
result.user; // User — narrowed, no optional chaining needed

AsyncStatus

HookResult covers actions you call. A hook that acts on mount reports a status instead, and they all use one vocabulary:

type AsyncStatus = 'pending' | 'error' | 'success';

There is no idle state — the work starts before you can render, so pending is where it begins. useVerifyEmail reports it as VerifyEmailStatus, an alias of this.

Actions you call get one more state, because nothing runs until you call them:

type ActionStatus = 'idle' | AsyncStatus;

Every action hook returns status: ActionStatus with isIdle, isPending, isSuccess and isError derived from it, plus reset(). Two vocabularies rather than one is deliberate — the same split TanStack Query makes between a query's status and a mutation's.

Render the three branches and you've handled every case:

if (status === 'pending') return <Spinner />;
if (status === 'error') return <ErrorState message={error} />;
return <Success />;

HookErrorOptions — the formatErrorMessage option every hook accepts.

HookErrorContext — what the provider's onError observer receives: { action, code, message }.

On this page