How every hook works
One contract, so learning one hook is learning them all.
Every hook in this package follows the same shape. Once you've used one, the rest are predictable.
Every hook needs an Auth instance
Below an AuthProvider the hooks take its auth, so there's nothing to pass:
const { login } = useLogin();
const { signup } = useSignup({ sendVerificationEmail: false });You can still pass one explicitly, and it wins over the provider's. That's what a second Firebase project needs, and it's the only option if you're not using a provider at all:
const { login } = useLogin(auth);
const { login } = useLogin(auth, { onIdToken: createSession });auth comes from the firebase package, not this one — getAuth(initializeApp(config)), created once in your app and imported where you need it. Getting started has the file in full.
Passing null is always safe, and it never means "use the provider's". It means the instance isn't ready: state hooks report loading, and actions fail cleanly with { success: false, error, code, cause } rather than throwing. That distinction is what lets you hold a hook back while Firebase boots without it quietly running against the provider's instance instead.
const { login } = useLogin(auth); // auth may still be null here — fineEvery action resolves to a result
Actions never throw. Each resolves to a HookResult:
{ success: true, ...data }
// or
{ success: false, error, code, cause }The hook's own error state carries the same message for rendering, and loading tracks the action. Some hooks also expose success and resetState.
const result = await login(email, password);
if (result.success) router.push('/dashboard');
else if (result.code === 'auth/too-many-requests') startCooldown();See Error handling for the full model.
onIdToken runs after a successful sign-in
With a freshly minted token, so you can trade it for a server session. Throwing inside it aborts the flow, and the error surfaces like any other failure.
const { login } = useLogin({
onIdToken: (idToken, user) => createSession(idToken),
});See Server sessions.
currentPassword triggers reauthentication
Firebase rejects sensitive operations on a stale sign-in. Pass currentPassword to useUpdatePassword, useUpdateEmail, or useDeleteAccount and the hook reauthenticates first.
Omit it — OAuth-only accounts have no password — and auth/requires-recent-login reaches you through code and cause, so you can run your own policy with useReauthenticate.
Provider options are defaults, hook options win
onIdToken, onBeforeSignOut, actionCodeSettings, formatErrorMessage, and the onError observer can all be set once on AuthProvider.
A hook's own option overrides the provider, and an explicit null opts that flow out entirely.
<AuthProvider auth={auth} onIdToken={createSession}>
{children}
</AuthProvider>;
const { login } = useLogin(); // inherits session minting
const { login } = useLogin({ onIdToken: null }); // opts out