Skip to content

Expose a userLoaded state from useCurrentUser to avoid "flash of logged out nav" #1306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Soviut opened this issue Feb 13, 2023 · 2 comments · Fixed by #1307
Closed

Expose a userLoaded state from useCurrentUser to avoid "flash of logged out nav" #1306

Soviut opened this issue Feb 13, 2023 · 2 comments · Fixed by #1307

Comments

@Soviut
Copy link
Contributor

Soviut commented Feb 13, 2023

What problem is this solving

The useCurrentUser composable returns a nullable ref of the current user. However, it can also be undefined while the user is still loading. It is common practice to hide navigation to areas that a logged out user should not be able to access. If a user is logged in already and refreshes the page they will see a brief "flash of logged out nav" before the user finishes loading and the logged in nav appears.

<script setup>
const currentUser = useCurrentUser()
</script>

<nav>
  <router-link v-if="currentUser" to="/logout">Logout</router-link>
  <router-link v-else to="/login">Login</router-link>
</nav>

Proposed solution

It would be useful if an explicit userLoaded state were exposed from the useCurrentUser composable. Something that does the following.

const userLoaded = computed(() => typeof currentUser.value !== 'undefined')

So that it could be used like this.

<script setup>
const { currentUser, userLoaded } = useCurrentUser()
</script>

<nav v-show="userLoaded">
  <router-link v-if="currentUser" to="/logout">Logout</router-link>
  <router-link v-else to="/login">Login</router-link>
</nav>

I've found that using v-show is best in this case since it doesn't cause the DOM to reflow like v-if does on the top level nav.

Describe alternatives you've considered

Currently I do the following instead.

<script setup>
const currentUser = useCurrentUser()
const userLoaded = computed(() => typeof currentUser.value !== 'undefined')
</script>

<nav v-show="userLoaded">
  <router-link v-if="currentUser" to="/logout">Logout</router-link>
  <router-link v-else to="/login">Login</router-link>
</nav>

I realize this isn't a lot of work to do, but having a formal implementation would mean it's easier to document the pattern.

Additional Considerations

This would change how the API works since useCurrentUser returns a user, not an object with a user in it.

Copy link
Member

posva commented Feb 13, 2023

I would rather not break the API unless necessary or if it really improves it. In this case, I think exposing a new function instead makes more sense:

const isUserLoaded = useIsUserLoaded()

@Soviut
Copy link
Contributor Author

Soviut commented Feb 13, 2023

@posva Great, I'm doing a quick PR for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants