From cd9dd9ddc063b60b07599dedef92182c0bd19f82 Mon Sep 17 00:00:00 2001 From: "Eray Erdin (&mut self)" Date: Sun, 18 Feb 2024 00:35:29 +0300 Subject: [PATCH] Add positional parameters to Auth hooks (#76) * make auth parameter positional * add cannot delete another user warning * rewrite document for positional parameters * refactor parameters * rewrite docs for positional parameters * refactor positional parameters * rewrite docs for positional parameters * refactor positional parameters * rewrite docs for positional parameters * refactor positional parameters * rewrite docs for positional parameters * refactor positional parameters * rewrite docs for positional parameters * fix useUser parameters * fix linting issue * fix useUser parameters * fix linting issue --- docs/hooks/useDeleteUser.md | 12 ++++++++---- docs/hooks/useSendEmailVerification.md | 4 ++-- docs/hooks/useSignIn.md | 8 ++++---- docs/hooks/useSignOut.md | 19 ++++++++++--------- docs/hooks/useSignUp.md | 4 ++-- docs/hooks/useUser.md | 7 ++++--- src/auth/AuthorizationZone.tsx | 2 +- src/auth/SignOut.tsx | 2 +- src/auth/useDeleteUser.test.ts | 12 ++++++------ src/auth/useDeleteUser.ts | 15 ++++++++------- src/auth/useSendEmailVerification.ts | 12 ++++-------- src/auth/useSignIn.test.ts | 8 ++++---- src/auth/useSignIn.ts | 8 ++------ src/auth/useSignOut.test.tsx | 18 ++++++++++-------- src/auth/useSignOut.ts | 15 ++++++++------- src/auth/useSignUp.test.ts | 12 ++++++------ src/auth/useSignUp.ts | 8 ++------ src/auth/useUser.test.tsx | 6 +++--- src/auth/useUser.ts | 15 ++++++++------- 19 files changed, 93 insertions(+), 94 deletions(-) diff --git a/docs/hooks/useDeleteUser.md b/docs/hooks/useDeleteUser.md index 098c378..2fe6162 100644 --- a/docs/hooks/useDeleteUser.md +++ b/docs/hooks/useDeleteUser.md @@ -8,17 +8,20 @@ tags: `useDeleteUser` hook is used to delete the currently signed-in user. A very simple example would be: ```typescript -const { dispatch } = useDeleteUser({ auth }); +const { dispatch } = useDeleteUser(auth); await dispatch(); ``` +!!! warning + `useDeleteUser`, as mentioned, can only delete the currently signed-in user from the client side. Due to security reasons, you cannot delete any other user. If you want to delete another user, use Firebase Auth from Firebase Console or Firebase Functions. + !!! warning `useDeleteUser` is lazy by default and will not do anything until you use `dispatch` function. You can also get the state[^unauthorized] of deletion process. ```typescript -const { state, dispatch } = useDeleteUser({ auth }); +const { state, dispatch } = useDeleteUser(auth); await dispatch(); // `state` is "ready" | "loading" | "anonymous" ``` @@ -30,7 +33,7 @@ By default, `"anonymous"` state includes both real anonymous and Firebase-handle ```typescript // assuming user is Firebase-handled anon -const { dispatch } = useDeleteUser({ auth, includeFirebaseAnon: true }); +const { dispatch } = useDeleteUser(auth, { includeFirebaseAnon: true }); await dispatch(); // this will delete anonymous user ``` @@ -41,7 +44,8 @@ Input parameters for `useDeleteUser` hook is as follows: | Name | Type | Description | Required | Default Value | |---|---|---|---|---| | `auth` | [`firebase/auth/Auth`][AuthRefDoc] | Reference to the Firebase Auth service instance. | ✅ | - | -| `includeFirebaseAnon` | `boolean` | Enable deleting Firebase-handled anonymous users. | ❌ | `false` | +| `options` | `Object` | Options for the operation. | ❌ | See below. | +| `options.includeFirebaseAnon` | `boolean` | Enable deleting Firebase-handled anonymous users. | ❌ | `false` | ## Return Type diff --git a/docs/hooks/useSendEmailVerification.md b/docs/hooks/useSendEmailVerification.md index 1065027..cb05ebe 100644 --- a/docs/hooks/useSendEmailVerification.md +++ b/docs/hooks/useSendEmailVerification.md @@ -8,7 +8,7 @@ tags: `useSendEmailVerification` hook is used to send email verification to a user. A very simple example would be: ```typescript -const { dispatch } = useSendEmailVerification({ auth }); +const { dispatch } = useSendEmailVerification(auth); await dispatch(); ``` @@ -18,7 +18,7 @@ await dispatch(); You can also get the state of the process. ```typescript -const { state, dispatch } = useSendEmailVerification({ auth }); +const { state, dispatch } = useSendEmailVerification(auth); await dispatch(); // `state` is "ready" | "loading" | "done" | "anonymous" ``` diff --git a/docs/hooks/useSignIn.md b/docs/hooks/useSignIn.md index c54e442..0b9455e 100644 --- a/docs/hooks/useSignIn.md +++ b/docs/hooks/useSignIn.md @@ -8,7 +8,7 @@ tags: `useSignIn` hook is used to sign in a user. A very simple example would be: ```typescript -const { dispatch } = useSignIn({ auth }); +const { dispatch } = useSignIn(auth); await dispatch({ type: "classic", email, @@ -22,7 +22,7 @@ await dispatch({ You can also get the state[^unauthorized] of sign-in process. ```typescript -const { state, dispatch } = useSignIn({ auth }); +const { state, dispatch } = useSignIn(auth); await dispatch({ type: "classic", email, @@ -37,7 +37,7 @@ await dispatch({ `dispatch` function will return an instance of [`UserCredential` | `undefined`][UserCredentialDocRef]. ```typescript -const { state, dispatch } = useSignIn({ auth }); +const { state, dispatch } = useSignIn(auth); const credential = await dispatch({ type: "classic", email, @@ -116,7 +116,7 @@ You will need `actionCodeSettings`. You can see [this section in Firebase Auth d If `type` is something else, you need to provide an implementation of `AuthProvider`. An example for Google sign-in looks as such: ```typescript -const { state, dispatch } = useSignIn({ auth }); +const { state, dispatch } = useSignIn(auth); const provider = new GoogleAuthProvider(); await dispatch({ type: "google", diff --git a/docs/hooks/useSignOut.md b/docs/hooks/useSignOut.md index b76fbc3..0e80b60 100644 --- a/docs/hooks/useSignOut.md +++ b/docs/hooks/useSignOut.md @@ -8,7 +8,7 @@ tags: `useSignOut` hook is used to sign out currently signed-in user. A very simple example would be: ```typescript -const { dispatch } = useSignOut({ auth }); +const { dispatch } = useSignOut(auth); await dispatch(); ``` @@ -18,7 +18,7 @@ await dispatch(); You can also get the state[^done] of sign-out process. ```typescript -const { state, dispatch } = useSignOut({ auth }); +const { state, dispatch } = useSignOut(auth); await dispatch(); // `state` is "ready" | "loading" | "anonymous" ``` @@ -33,7 +33,7 @@ const onError = (error: Error) => { // do something with error } -const { dispatch } = useSignOut({ auth, onError }); +const { dispatch } = useSignOut(auth, { onError }); await dispatch(); ``` @@ -47,12 +47,12 @@ In Firebase, there are two types of anonymity: Firebase-handled anonymous users const onlyRealAnon = true; // User is really anonymous -const { state } = useSignOut({ auth }); // state: "anonymous" -const { state } = useSignOut({ auth, onlyRealAnon }); // state: "anonymous" +const { state } = useSignOut(auth); // state: "anonymous" +const { state } = useSignOut(auth, { onlyRealAnon }); // state: "anonymous" // User is anonymous in Firebase Auth records -const { state } = useSignOut({ auth }); // state: "anonymous" -const { state } = useSignOut({ auth, onlyRealAnon }); // state: "ready" +const { state } = useSignOut(auth); // state: "anonymous" +const { state } = useSignOut(auth, { onlyRealAnon }); // state: "ready" ``` ## Input Parameters @@ -62,8 +62,9 @@ Input parameters for `useSignOut` hook is as follows: | Name | Type | Description | Required | Default Value | |---|---|---|---|---| | `auth` | [`firebase/auth/Auth`][AuthRefDoc] | Reference to the Firebase Auth service instance. | ✅ | - | -| `onError` | `(error: Error) => void` | A function to handle errors. | ❌ | Throws error. | -| `onlyRealAnon` | `boolean` | Consider the user anonymous only if they are `null`. | ❌ | `false` (which also considers Firebase-handled anonymous users) | +| `options` | `Object` | Options for the process. | ❌ | See below. | +| `options.onError` | `(error: Error) => void` | A function to handle errors. | ❌ | Throws error. | +| `options.onlyRealAnon` | `boolean` | Consider the user anonymous only if they are `null`. | ❌ | `false` (which also considers Firebase-handled anonymous users) | ## Return Type diff --git a/docs/hooks/useSignUp.md b/docs/hooks/useSignUp.md index 3ec23a1..90d9068 100644 --- a/docs/hooks/useSignUp.md +++ b/docs/hooks/useSignUp.md @@ -8,7 +8,7 @@ tags: `useSignUp` hook is used to create a user with email and password. A very simple example would be: ```typescript -const { dispatch } = useSignUp({ auth }); +const { dispatch } = useSignUp(auth); await dispatch(email, password); ``` @@ -18,7 +18,7 @@ await dispatch(email, password); You can also get the state[^unauthorized] of sign-up process. ```typescript -const { state, dispatch } = useSignUp({ auth }); +const { state, dispatch } = useSignUp(auth); await dispatch(); // `state` is "ready" | "loading" | "authenticated" ``` diff --git a/docs/hooks/useUser.md b/docs/hooks/useUser.md index 2a8ebe3..ff78052 100644 --- a/docs/hooks/useUser.md +++ b/docs/hooks/useUser.md @@ -8,7 +8,7 @@ tags: `useUser` hook is used to get the currently signed-in user. A very simple example would be: ```typescript -const user = useUser({ auth }); +const user = useUser(auth); ``` !!! warning @@ -35,8 +35,9 @@ Input parameters for `useUser` hook is as follows: | Name | Type | Description | Required | Default Value | |---|---|---|---|---| | `auth` | [`firebase/auth/Auth`][AuthRefDoc] | Reference to the Firebase Auth service instance. | ✅ | - | -| `onError` | `(error: Error) => void` or `undefined` | A function to handle errors. | ❌ | `undefined` | -| `onChange` | `() => void` or `undefined` | A function to run after state changes. | ❌ | `undefined` | +| `options` | `Object` | Options for the process. | ❌ | See below. | +| `options.onError` | `(error: Error) => void` or `undefined` | A function to handle errors. | ❌ | `undefined` | +| `options.onChange` | `() => void` or `undefined` | A function to run after state changes. | ❌ | `undefined` | ## Return Type diff --git a/src/auth/AuthorizationZone.tsx b/src/auth/AuthorizationZone.tsx index 7ff2b31..effa1d4 100644 --- a/src/auth/AuthorizationZone.tsx +++ b/src/auth/AuthorizationZone.tsx @@ -24,7 +24,7 @@ export const AuthorizationZone = ({ onSuccess, onFailure = () => <>, }: AuthorizationZoneProps) => { - const user = useUser({ auth }); + const user = useUser(auth); const [success, setSuccess] = useState(false); useEffect(() => { diff --git a/src/auth/SignOut.tsx b/src/auth/SignOut.tsx index 4feacbf..efa0ef5 100644 --- a/src/auth/SignOut.tsx +++ b/src/auth/SignOut.tsx @@ -22,7 +22,7 @@ export const SignOut = ({ onLoading, onAnonymous, }: SignOutProps) => { - const { state, dispatch } = useSignOut({ auth, onlyRealAnon }); + const { state, dispatch } = useSignOut(auth, { onlyRealAnon }); switch (state) { case "ready": diff --git a/src/auth/useDeleteUser.test.ts b/src/auth/useDeleteUser.test.ts index 6a8aae1..a184f8d 100644 --- a/src/auth/useDeleteUser.test.ts +++ b/src/auth/useDeleteUser.test.ts @@ -26,7 +26,7 @@ describe("when real anon, useDeleteUser hook", () => { }); it("should have anonymous state", async () => { - const { result } = renderHook(() => useDeleteUser({ auth })); + const { result } = renderHook(() => useDeleteUser(auth)); const { state } = result.current; expect(state).toBe("anonymous"); }); @@ -45,14 +45,14 @@ describe("when anon, useDeleteUser hook", () => { }); it("should have anonymous state", async () => { - const { result } = renderHook(() => useDeleteUser({ auth })); + const { result } = renderHook(() => useDeleteUser(auth)); const { state } = result.current; expect(state).toBe("anonymous"); }); it("should have ready state if includeFirebaseAnon", async () => { const { result } = renderHook(() => - useDeleteUser({ auth, includeFirebaseAnon: true }), + useDeleteUser(auth, { includeFirebaseAnon: true }), ); const { state } = result.current; expect(state).toBe("ready"); @@ -88,13 +88,13 @@ describe("when authed, useDeleteUser hook", () => { }); it("should have ready state", async () => { - const { result } = renderHook(() => useDeleteUser({ auth })); + const { result } = renderHook(() => useDeleteUser(auth)); const { state } = result.current; expect(state).toBe("ready"); }); it("should delete user", async () => { - const { result } = renderHook(() => useDeleteUser({ auth })); + const { result } = renderHook(() => useDeleteUser(auth)); const { dispatch } = result.current; await dispatch(); await sleep(100); @@ -103,7 +103,7 @@ describe("when authed, useDeleteUser hook", () => { }); it("should have loading state while dispatching", async () => { - const { result } = renderHook(() => useDeleteUser({ auth })); + const { result } = renderHook(() => useDeleteUser(auth)); const { dispatch } = result.current; dispatch(); await sleep(1); diff --git a/src/auth/useDeleteUser.ts b/src/auth/useDeleteUser.ts index 0feaa03..5c0c8dc 100644 --- a/src/auth/useDeleteUser.ts +++ b/src/auth/useDeleteUser.ts @@ -7,8 +7,7 @@ import { Auth, deleteUser, signOut } from "firebase/auth"; import { useEffect, useState } from "react"; import { useUser } from "."; -type UseDeleteUserParams = { - auth: Auth; +type UseDeleteUserOptions = { includeFirebaseAnon?: boolean; }; @@ -19,11 +18,13 @@ type UseDeleteUser = { dispatch: UseDeleteUserDispatcher; }; -export const useDeleteUser = ({ - auth, - includeFirebaseAnon = false, -}: UseDeleteUserParams): UseDeleteUser => { - const user = useUser({ auth }); +export const useDeleteUser = ( + auth: Auth, + { includeFirebaseAnon }: UseDeleteUserOptions = { + includeFirebaseAnon: false, + }, +): UseDeleteUser => { + const user = useUser(auth); const [state, setState] = useState("ready"); useEffect(() => { diff --git a/src/auth/useSendEmailVerification.ts b/src/auth/useSendEmailVerification.ts index 1e7d1a8..2aa68e0 100644 --- a/src/auth/useSendEmailVerification.ts +++ b/src/auth/useSendEmailVerification.ts @@ -7,10 +7,6 @@ import { ActionCodeSettings, Auth, sendEmailVerification } from "firebase/auth"; import { useEffect, useState } from "react"; import { useUser } from "."; -type UseSendEmailVerificationParams = { - auth: Auth; -}; - type UseSendEmailVerificationState = "ready" | "loading" | "done" | "anonymous"; type UseSendEmailVerificationDispatcher = ( actionCodeSettings?: ActionCodeSettings, @@ -20,10 +16,10 @@ type UseSendEmailVerification = { dispatch: UseSendEmailVerificationDispatcher; }; -export const useSendEmailVerification = ({ - auth, -}: UseSendEmailVerificationParams): UseSendEmailVerification => { - const user = useUser({ auth }); +export const useSendEmailVerification = ( + auth: Auth, +): UseSendEmailVerification => { + const user = useUser(auth); const [state, setState] = useState("ready"); useEffect(() => { diff --git a/src/auth/useSignIn.test.ts b/src/auth/useSignIn.test.ts index f06f482..208f90b 100644 --- a/src/auth/useSignIn.test.ts +++ b/src/auth/useSignIn.test.ts @@ -34,7 +34,7 @@ describe("when authed, useSignIn hook", () => { }); it("should have authenticated state", async () => { - const { result } = renderHook(() => useSignIn({ auth })); + const { result } = renderHook(() => useSignIn(auth)); const { state } = result.current; expect(state).toBe("authenticated"); }); @@ -46,7 +46,7 @@ describe("when anon, useSignIn hook", () => { await signOut(auth); // test - const { result } = renderHook(() => useSignIn({ auth })); + const { result } = renderHook(() => useSignIn(auth)); const { state } = result.current; expect(state).toBe("ready"); }); @@ -56,7 +56,7 @@ describe("when anon, useSignIn hook", () => { const credential = await signInAnonymously(auth); // test - const { result } = renderHook(() => useSignIn({ auth })); + const { result } = renderHook(() => useSignIn(auth)); const { state } = result.current; expect(state).toBe("ready"); @@ -70,7 +70,7 @@ describe("when anon, useSignIn hook", () => { const email = generateEmail("dispatchemail"); await createUserWithEmailAndPassword(auth, email, password); - const { result } = renderHook(() => useSignIn({ auth })); + const { result } = renderHook(() => useSignIn(auth)); const { dispatch } = result.current; const credential = await dispatch({ type: "classic", email, password }); diff --git a/src/auth/useSignIn.ts b/src/auth/useSignIn.ts index be1d51c..b38eefd 100644 --- a/src/auth/useSignIn.ts +++ b/src/auth/useSignIn.ts @@ -19,10 +19,6 @@ import { ActionCodeSettings } from "firebase/auth"; import { useEffect, useState } from "react"; import { useUser } from "."; -type UseSignInParams = { - auth: Auth; -}; - type UseSignInState = "ready" | "loading" | "authenticated" | "awaiting"; type UseSignInDispatcher = ( params: @@ -62,8 +58,8 @@ type UseSignIn = { dispatch: UseSignInDispatcher; }; -export const useSignIn = ({ auth }: UseSignInParams): UseSignIn => { - const user = useUser({ auth }); +export const useSignIn = (auth: Auth): UseSignIn => { + const user = useUser(auth); const [state, setState] = useState("ready"); useEffect(() => { diff --git a/src/auth/useSignOut.test.tsx b/src/auth/useSignOut.test.tsx index c7f0f3b..ce31418 100644 --- a/src/auth/useSignOut.test.tsx +++ b/src/auth/useSignOut.test.tsx @@ -19,7 +19,7 @@ const email = "usesignout@hook.com" as const; const password = "111111"; const SampleComponent = () => { - const user = useUser({ auth }); + const user = useUser(auth); return
{user ? "authed" : "real anon"}
; }; @@ -37,13 +37,15 @@ describe("when authed, useSignOut hook", () => { }); it("should have ready state", () => { - const { result } = renderHook(() => useSignOut({ auth })); + const { result } = renderHook(() => useSignOut(auth)); expect(result.current.state).toBe("ready"); }); - + { + auth; + } it("should sign out", async () => { render(); - const { result } = renderHook(() => useSignOut({ auth })); + const { result } = renderHook(() => useSignOut(auth)); const { dispatch } = result.current; await dispatch(); await sleep(100); @@ -52,7 +54,7 @@ describe("when authed, useSignOut hook", () => { it("should have anonymous state after dispatched", async () => { render(); - const { result } = renderHook(() => useSignOut({ auth })); + const { result } = renderHook(() => useSignOut(auth)); const { dispatch } = result.current; await dispatch(); await sleep(100); @@ -63,7 +65,7 @@ describe("when authed, useSignOut hook", () => { describe("when real anon, useSignOut hook", () => { it("should have anonymous state", () => { - const { result } = renderHook(() => useSignOut({ auth })); + const { result } = renderHook(() => useSignOut(auth)); expect(result.current.state).toBe("anonymous"); }); }); @@ -74,13 +76,13 @@ describe("when anon, useSignOut hook", () => { }); it("should have anonymous state", () => { - const { result } = renderHook(() => useSignOut({ auth })); + const { result } = renderHook(() => useSignOut(auth)); expect(result.current.state).toBe("anonymous"); }); it("should have ready state if onlyRealAnon", () => { const { result } = renderHook(() => - useSignOut({ auth, onlyRealAnon: true }), + useSignOut(auth, { onlyRealAnon: true }), ); expect(result.current.state).toBe("ready"); }); diff --git a/src/auth/useSignOut.ts b/src/auth/useSignOut.ts index 7cf242f..3a237ce 100644 --- a/src/auth/useSignOut.ts +++ b/src/auth/useSignOut.ts @@ -8,7 +8,6 @@ import { useEffect, useState } from "react"; import { useUser } from "."; type UseSignOutParams = { - auth: Auth; onError?: (error: Error) => void; onlyRealAnon?: boolean; }; @@ -21,13 +20,15 @@ type UseSignOut = { dispatch: UseSignOutDispatcher; }; -export const useSignOut = ({ - auth, - onError, - onlyRealAnon = false, -}: UseSignOutParams): UseSignOut => { +export const useSignOut = ( + auth: Auth, + { onError, onlyRealAnon }: UseSignOutParams = { + onError: () => {}, + onlyRealAnon: false, + }, +): UseSignOut => { const [state, setState] = useState("ready"); - const user = useUser({ auth, onError }); + const user = useUser(auth, { onError }); useEffect(() => { // if (!user || user.isAnonymous) { diff --git a/src/auth/useSignUp.test.ts b/src/auth/useSignUp.test.ts index 34931d9..c8b1d6c 100644 --- a/src/auth/useSignUp.test.ts +++ b/src/auth/useSignUp.test.ts @@ -41,7 +41,7 @@ describe("when authed, useSignUp hook", () => { }); it("should have authenticated state", async () => { - const { result } = renderHook(() => useSignUp({ auth })); + const { result } = renderHook(() => useSignUp(auth)); const { state } = result.current; expect(state).toBe("authenticated"); }); @@ -49,13 +49,13 @@ describe("when authed, useSignUp hook", () => { describe("when real anon, useSignUp hook", () => { it("should have ready state", async () => { - const { result } = renderHook(() => useSignUp({ auth })); + const { result } = renderHook(() => useSignUp(auth)); const { state } = result.current; expect(state).toBe("ready"); }); it("should have loading state while dispatched", async () => { - const { result } = renderHook(() => useSignUp({ auth })); + const { result } = renderHook(() => useSignUp(auth)); const { dispatch } = result.current; dispatch(generateEmail("realanon"), password) .then(async (credential) => { @@ -72,7 +72,7 @@ describe("when real anon, useSignUp hook", () => { }); it("should sign up", async () => { - const { result } = renderHook(() => useSignUp({ auth })); + const { result } = renderHook(() => useSignUp(auth)); const { dispatch } = result.current; await dispatch(generateEmail("realanon2"), password); const localCredential = await signInWithEmailAndPassword( @@ -101,13 +101,13 @@ describe("when anon, useSignUp hook", () => { }); it("should have ready state", () => { - const { result } = renderHook(() => useSignUp({ auth })); + const { result } = renderHook(() => useSignUp(auth)); const { state } = result.current; expect(state).toBe("ready"); }); it("should sign up", async () => { - const { result } = renderHook(() => useSignUp({ auth })); + const { result } = renderHook(() => useSignUp(auth)); const { dispatch } = result.current; await dispatch(generateEmail("anon"), password); const localCredential = await signInWithEmailAndPassword( diff --git a/src/auth/useSignUp.ts b/src/auth/useSignUp.ts index 8f67fa0..fd55a19 100644 --- a/src/auth/useSignUp.ts +++ b/src/auth/useSignUp.ts @@ -11,10 +11,6 @@ import { import { useEffect, useState } from "react"; import { useUser } from "."; -type UseSignUpParams = { - auth: Auth; -}; - type UseSignUpState = "ready" | "loading" | "authenticated"; type UseSignUpDispatcher = ( email: string, @@ -25,8 +21,8 @@ type UseSignUp = { dispatch: UseSignUpDispatcher; }; -export const useSignUp = ({ auth }: UseSignUpParams): UseSignUp => { - const user = useUser({ auth }); +export const useSignUp = (auth: Auth): UseSignUp => { + const user = useUser(auth); const [state, setState] = useState("ready"); useEffect(() => { diff --git a/src/auth/useUser.test.tsx b/src/auth/useUser.test.tsx index f04a03e..d61eddd 100644 --- a/src/auth/useUser.test.tsx +++ b/src/auth/useUser.test.tsx @@ -18,7 +18,7 @@ import { useUser } from "./useUser"; describe("when real anon, useUser hook", () => { const RealAnonUserComponent = () => { - const user = useUser({ auth }); + const user = useUser(auth); return
{user ? "not real anon detected" : "real anon detected"}
; }; @@ -34,7 +34,7 @@ describe("when real anon, useUser hook", () => { describe("when anon, useUser", () => { const AnonUserComponent = () => { - const user = useUser({ auth }); + const user = useUser(auth); return (
{user?.isAnonymous ? "anon detected" : "non anon detected"}
); @@ -60,7 +60,7 @@ describe("when anon, useUser", () => { describe("when authed, useUser", () => { const AuthedUserComponent = () => { - const user = useUser({ auth }); + const user = useUser(auth); return
{user?.email}
; }; diff --git a/src/auth/useUser.ts b/src/auth/useUser.ts index f3dfa06..8fec7a2 100644 --- a/src/auth/useUser.ts +++ b/src/auth/useUser.ts @@ -12,17 +12,18 @@ import { } from "firebase/auth"; import { useEffect, useState } from "react"; -type UseAuthStateParams = { - auth: Auth; +type UseAuthStateOptions = { onError?: ErrorFn; onChange?: CompleteFn; }; -export const useUser = ({ - auth, - onError, - onChange, -}: UseAuthStateParams): User | null => { +export const useUser = ( + auth: Auth, + { onError, onChange }: UseAuthStateOptions = { + onError: () => {}, + onChange: () => {}, + }, +): User | null => { const [user, setUser] = useState(auth.currentUser); useEffect(() => {