0

I have setup a route in vue-router 4 that should load a component dynamically depending on whether the user is logged in or not. I did it like this (there may be a better way?):

import Personal from '../views/Personal.vue';
import Public from '../views/Public.vue';
routes: [
    {
        path: '/',
        component: async () => {
            const isLoggedIn = await authenticateUser();
            if (isLoggedIn == true) {
                return Personal
            } else {
               return Public
            }
        }
    }
]

The App.vue file is this:

<template>
  <div id="app">
      <Site-Header></Site-Header>
          <router-view></router-view>
    <Site-Footer></Site-Footer>
  </div>
</template>

The problem is that if a user logs in from the homepage route with path of '/', he doesn't navigate away from this route. Instead I would like vue-router to just load the Personal component instead.

The switch between Personal and Public only seems to work if I hard refresh the page, otherwise no changes happen. So if a user logs in, they still see the Public.vue component, then after a page refresh they see the Personal.vue component. If they then logout, they still see the Personal.vue component until they refresh the page.

How could I force vue-router to analyse the route after log-in/log-out and load the correct component?

volume one
  • 6,800
  • 13
  • 67
  • 146
  • A better solution than dynamic components (especially a root component that gets loaded in first) is to use a combination of [router meta fields](https://router.vuejs.org/guide/advanced/meta.html) & [route navigation guards](https://router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards) – Sensanaty Oct 02 '21 at 12:03
  • @Sensanaty I don't want the URL to change from `/` to say `/personal`. I want the view to change on the same route of `/`. – volume one Oct 02 '21 at 12:07
  • In that case you can utilize [named views](https://next.router.vuejs.org/guide/essentials/named-views.html) and simply switch between two routes using a `v-if` ` ` – Sensanaty Oct 02 '21 at 12:12
  • @Sensanaty That is what I'm trying to do in the `routes[]` part but because the path does not change, I am not getting a reload of the route. Updated my question with more code. – volume one Oct 02 '21 at 12:17
  • 1
    You're misunderstanding how named views work. I've made a quick example [here](https://codesandbox.io/s/sleepy-surf-lcq3p?file=/src/lib/router.js) that you can check out that demonstrates how you can achieve this using Named Views. Note that the router `components` definition is PLURAL, rather than singular. – Sensanaty Oct 02 '21 at 12:42

1 Answers1

1

To have multiple routes utilizing the same path, your best bet is using Named Views. You can define the default component for your index, or / path to be your Public component, while conditionally selecting a different component using v-if in your template.

You could define your routes as:

routes: [
  {
    components: {
      default: Public,
      Personal: Personal
    },
    name: "index",
    path: "/"
  }
]

Important to note that the syntax here differs. The component field here has to be pluralized in order for this to work, so it has to be components.

Then in your root template that's calling the views, you can then use a simple v-if to switch between them, depending on whether the user is logged in or not. How you store that information is up to you, so just adapt the below code to reflect your own app's logic

<!-- The default is Public, so you don't have to provide the name here -->
<router-view v-if="!user.loggedIn" />
<router-view v-else name="Personal" />

You can see this in this codesandbox

Sensanaty
  • 894
  • 1
  • 12
  • 35