From 59d0cfe43510a8aaa4becb4b0ca21a46a9ec1413 Mon Sep 17 00:00:00 2001 From: Ian Zamojc Date: Mon, 13 Feb 2023 04:27:10 -0500 Subject: [PATCH 01/10] feat(auth): added isUserLoaded composable --- src/auth/index.ts | 1 + src/auth/user.ts | 12 +++++++++++- src/index.ts | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/auth/index.ts b/src/auth/index.ts index fb33e667..885d53d9 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -8,6 +8,7 @@ import { authUserMap, setupOnAuthStateChanged } from './user' export { useCurrentUser, + isUserLoaded, getCurrentUser, updateCurrentUserProfile, updateCurrentUserEmail, diff --git a/src/auth/user.ts b/src/auth/user.ts index 0e3824af..ae5ae1b4 100644 --- a/src/auth/user.ts +++ b/src/auth/user.ts @@ -8,7 +8,7 @@ import { reauthenticateWithCredential, AuthCredential, } from 'firebase/auth' -import type { Ref } from 'vue-demi' +import { computed, Ref } from 'vue-demi' import { useFirebaseApp } from '../app' import type { _MaybeRef, _Nullable } from '../shared' @@ -36,6 +36,16 @@ export function useCurrentUser(name?: string) { return authUserMap.get(useFirebaseApp(name))! } +/** + * Returns a boolean indicating if the current user has finished loading and is no longer undefined. This is useful for + * hiding navigation until the current user is loaded and we know if they are authenticated or not. + * @param name - name of the application + */ +export function isUserLoaded(name?: string) { + const currentUser = useCurrentUser(name) + return computed(() => typeof currentUser !== 'undefined') +} + /** * Updates the current user profile and updates the current user state. This function internally calls `updateProfile()` * from 'firebase/auth' and then updates the current user state. diff --git a/src/index.ts b/src/index.ts index c93d50da..f8479c31 100644 --- a/src/index.ts +++ b/src/index.ts @@ -78,6 +78,7 @@ export { useFirebaseApp } from './app' */ export { useCurrentUser, + isUserLoaded, VueFireAuth, useFirebaseAuth, getCurrentUser, From eba5c8625cf8b86daba661b870b8a7ef36afb7d4 Mon Sep 17 00:00:00 2001 From: Soviut Date: Mon, 13 Feb 2023 12:40:10 -0500 Subject: [PATCH 02/10] Update src/auth/user.ts Co-authored-by: Eduardo San Martin Morote --- src/auth/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth/user.ts b/src/auth/user.ts index ae5ae1b4..390e0df7 100644 --- a/src/auth/user.ts +++ b/src/auth/user.ts @@ -43,7 +43,7 @@ export function useCurrentUser(name?: string) { */ export function isUserLoaded(name?: string) { const currentUser = useCurrentUser(name) - return computed(() => typeof currentUser !== 'undefined') + return computed(() => currentUser !== undefined) } /** From 6e3f79572b8079b3d932977af304575b61c1326d Mon Sep 17 00:00:00 2001 From: Soviut Date: Mon, 13 Feb 2023 12:41:40 -0500 Subject: [PATCH 03/10] Update src/auth/user.ts Co-authored-by: Eduardo San Martin Morote --- src/auth/user.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/auth/user.ts b/src/auth/user.ts index 390e0df7..7f17bb22 100644 --- a/src/auth/user.ts +++ b/src/auth/user.ts @@ -39,6 +39,7 @@ export function useCurrentUser(name?: string) { /** * Returns a boolean indicating if the current user has finished loading and is no longer undefined. This is useful for * hiding navigation until the current user is loaded and we know if they are authenticated or not. + * * @param name - name of the application */ export function isUserLoaded(name?: string) { From cc54f787b4e1ce5f11fe4ebf19ab321d78f48540 Mon Sep 17 00:00:00 2001 From: Soviut Date: Mon, 13 Feb 2023 13:13:28 -0500 Subject: [PATCH 04/10] Update src/auth/user.ts Co-authored-by: Eduardo San Martin Morote --- src/auth/user.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/auth/user.ts b/src/auth/user.ts index 7f17bb22..a9e43976 100644 --- a/src/auth/user.ts +++ b/src/auth/user.ts @@ -37,8 +37,7 @@ export function useCurrentUser(name?: string) { } /** - * Returns a boolean indicating if the current user has finished loading and is no longer undefined. This is useful for - * hiding navigation until the current user is loaded and we know if they are authenticated or not. + * Helper that returns a computed boolean that becomes `true` as soon as the current user is no longer `undefined`. Note this doesn't ensure the user is logged in, only if the initial signing process has run. * * @param name - name of the application */ From 446af987fe599c446441a3f740b6b8803fdaf384 Mon Sep 17 00:00:00 2001 From: Ian Zamojc Date: Mon, 13 Feb 2023 13:16:55 -0500 Subject: [PATCH 05/10] fix: renamed to useIsUserLoaded --- src/auth/index.ts | 2 +- src/auth/user.ts | 2 +- src/index.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth/index.ts b/src/auth/index.ts index 885d53d9..42ec1772 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -8,7 +8,7 @@ import { authUserMap, setupOnAuthStateChanged } from './user' export { useCurrentUser, - isUserLoaded, + useIsUserLoaded, getCurrentUser, updateCurrentUserProfile, updateCurrentUserEmail, diff --git a/src/auth/user.ts b/src/auth/user.ts index a9e43976..cc4986f9 100644 --- a/src/auth/user.ts +++ b/src/auth/user.ts @@ -41,7 +41,7 @@ export function useCurrentUser(name?: string) { * * @param name - name of the application */ -export function isUserLoaded(name?: string) { +export function useIsUserLoaded(name?: string) { const currentUser = useCurrentUser(name) return computed(() => currentUser !== undefined) } diff --git a/src/index.ts b/src/index.ts index f8479c31..f43d9c63 100644 --- a/src/index.ts +++ b/src/index.ts @@ -78,7 +78,7 @@ export { useFirebaseApp } from './app' */ export { useCurrentUser, - isUserLoaded, + useIsUserLoaded, VueFireAuth, useFirebaseAuth, getCurrentUser, From 049f9d367242e11b5b896022b442cde5cca1778f Mon Sep 17 00:00:00 2001 From: Ian Zamojc Date: Mon, 13 Feb 2023 13:30:50 -0500 Subject: [PATCH 06/10] docs: for useIsUserLoaded --- docs/guide/auth.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/guide/auth.md b/docs/guide/auth.md index 4ec3fef6..b135ba41 100644 --- a/docs/guide/auth.md +++ b/docs/guide/auth.md @@ -46,6 +46,32 @@ const user = useCurrentUser() ``` +### Avoid "flash of logged out navigation" on page load + +It is common to hide or disable navigation links when the user is not logged in. However, when the page loads, the user is loaded asynchronously. This can result in a "flash of logged out navigation" where the navigation links are displayed briefly before the user is loaded. + +To avoid this, you can use the `useIsUserLoaded()` composable to check if the user is loaded and only then display the navigation links. + +```vue + + + +``` + +::: tip +Using `v-show` instead of `v-if` to hide the navigation will avoid an unnecessary DOM reflow and be less noticable. +::: + ### Wait for the user to be loaded There is also a `getCurrentUser()` function that returns a promise of the current user. This is useful if you want to wait for the user to be loaded before doing anything. You can, for example, await it within a navigation guard: From 34c3ef65422201357efc1c3dda59ccf79075447d Mon Sep 17 00:00:00 2001 From: Ian Zamojc Date: Mon, 13 Feb 2023 14:35:10 -0500 Subject: [PATCH 07/10] docs: tip --- docs/guide/auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/auth.md b/docs/guide/auth.md index b135ba41..db16da64 100644 --- a/docs/guide/auth.md +++ b/docs/guide/auth.md @@ -69,7 +69,7 @@ const isUserLoaded = useIsUserLoaded() ``` ::: tip -Using `v-show` instead of `v-if` to hide the navigation will avoid an unnecessary DOM reflow and be less noticable. +Note this does not ensure the user is logged in, only if the initial signing process has run. You still need to check if `currentUser` is `null` or not. ::: ### Wait for the user to be loaded From 89fa32f5b95ed62b50490b77cb39b55dad1c8a02 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 14 Feb 2023 09:31:07 +0100 Subject: [PATCH 08/10] docs: refactor --- docs/guide/auth.md | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/docs/guide/auth.md b/docs/guide/auth.md index db16da64..5156ea0f 100644 --- a/docs/guide/auth.md +++ b/docs/guide/auth.md @@ -46,34 +46,10 @@ const user = useCurrentUser() ``` -### Avoid "flash of logged out navigation" on page load - -It is common to hide or disable navigation links when the user is not logged in. However, when the page loads, the user is loaded asynchronously. This can result in a "flash of logged out navigation" where the navigation links are displayed briefly before the user is loaded. - -To avoid this, you can use the `useIsUserLoaded()` composable to check if the user is loaded and only then display the navigation links. - -```vue - - - -``` - -::: tip -Note this does not ensure the user is logged in, only if the initial signing process has run. You still need to check if `currentUser` is `null` or not. -::: - ### Wait for the user to be loaded +The `useCurrentUser()` composable will give you an `undefined` value until the user is loaded. It will then become `null` or the user object itself. If you need to wait for the user to be loaded in a declarative fashion, you can use the `useIsCurrentUserLoaded()` composable. Internally it's just a computed property that returns `true` when if user is not `undefined`. + There is also a `getCurrentUser()` function that returns a promise of the current user. This is useful if you want to wait for the user to be loaded before doing anything. You can, for example, await it within a navigation guard: ```ts From 0db548f90e0c06b832ee496f871f9b86a2530937 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 14 Feb 2023 09:31:44 +0100 Subject: [PATCH 09/10] style: rewrap --- src/auth/user.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/auth/user.ts b/src/auth/user.ts index cc4986f9..589f0804 100644 --- a/src/auth/user.ts +++ b/src/auth/user.ts @@ -37,7 +37,8 @@ export function useCurrentUser(name?: string) { } /** - * Helper that returns a computed boolean that becomes `true` as soon as the current user is no longer `undefined`. Note this doesn't ensure the user is logged in, only if the initial signing process has run. + * Helper that returns a computed boolean that becomes `true` as soon as the current user is no longer `undefined`. Note + * this doesn't ensure the user is logged in, only if the initial signing process has run. * * @param name - name of the application */ From 222ac375f4753392873f39c397a0471713381402 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 14 Feb 2023 09:35:17 +0100 Subject: [PATCH 10/10] refactor: rename --- src/auth/index.ts | 2 +- src/auth/user.ts | 2 +- src/index.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth/index.ts b/src/auth/index.ts index 42ec1772..d63b60f7 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -8,7 +8,7 @@ import { authUserMap, setupOnAuthStateChanged } from './user' export { useCurrentUser, - useIsUserLoaded, + useIsCurrentUserLoaded, getCurrentUser, updateCurrentUserProfile, updateCurrentUserEmail, diff --git a/src/auth/user.ts b/src/auth/user.ts index 589f0804..d01308d6 100644 --- a/src/auth/user.ts +++ b/src/auth/user.ts @@ -42,7 +42,7 @@ export function useCurrentUser(name?: string) { * * @param name - name of the application */ -export function useIsUserLoaded(name?: string) { +export function useIsCurrentUserLoaded(name?: string) { const currentUser = useCurrentUser(name) return computed(() => currentUser !== undefined) } diff --git a/src/index.ts b/src/index.ts index f43d9c63..ef06c16f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -78,7 +78,7 @@ export { useFirebaseApp } from './app' */ export { useCurrentUser, - useIsUserLoaded, + useIsCurrentUserLoaded, VueFireAuth, useFirebaseAuth, getCurrentUser,