jeff
jeff

Reputation: 97

How to re-render already mounted component after route change in vue?

The component which holds q-btn-dropdown is already rendered before the route change. The route change occurs when the user logs in, so the helloGuest() is called only once when the component which has the q-btn-dropdown. So how do I re-render the component which holds the q-btn-dropdown, so that helloGuest() is called and the q-btn-dropdown updates?

methods: {
login() {
  this.$axios.post('login', this.formData).then(async (res) => {
    console.log(res);
    await localStorage.setItem('user', JSON.stringify(res));
    await localStorage.setItem('token', res.token);
    this.$router.push('/');
  }).catch((error) => {
    this.error = {
      email: error.response.data.message,
    };
  });
},


   <q-btn-dropdown flat dense
    :label="helloGuest()"
    class="gt-xs"
    >
 helloGuest() {
  const userName = JSON.parse(localStorage.getItem('user')) || {};
  console.log('[isauth]', this.isAuthenticated);
  console.log('[userName]', userName);
  console.log('[router]', this.$router);
  if (this.isAuthenticated) {
    // this.$forceUpdate();
    return `Hello ${userName.username}`;
  }
  return 'Sign In';
},

my route file looks like this and I havent used mounted hook on the landing route

const routes = [{
path: '/',
component: () => import('layouts/MainDashboard.vue'),
children: [
  { path: '', component: () => import('components/FrontComponent.vue'), meta: { requiresAuth: false } },
  { path: '/product_details/:productId', component: () => import('components/ProductDetails.vue'), meta: { requiresAuth: false } },
  { path: '/cart', component: () => import('../cart/ShoppingCart.vue'), meta: { requiresAuth: false } },
  { path: '/checkout', component: () => import('../cart/CheckoutComponent.vue'), meta: { requiresAuth: false } },
  {
    path: '/login', name: 'Login', component: () => import('components/LoginComponent.vue'), meta: { requiresAuth: false },
  },
  { path: '/register', component: () => import('components/RegisterComponent.vue'), meta: { requiresAuth: false } },
],

Upvotes: 1

Views: 3393

Answers (3)

Andrey
Andrey

Reputation: 2068

Just make wrapper of your original component and assign the wrapper to the route instead of original component. Like as follows:

<script lang="ts" setup>
    import { useRoute } from "vue-router";
    import OriginalComponent from "./OriginalComponent.vue";
    const route=useRoute();
</script>

<template>
    <OriginalComponent :key="route.fullPath"></OriginalComponent>
</template>

Then assign the above to router

{
    path: "/some-path/:param",
    component: OriginalComponentWrapper,
},

That will lead to re-build of OriginalComponent on any route change, including parameters etc. onMounted of the OriginalComponent will be invoked

Upvotes: 0

jeff
jeff

Reputation: 97

The best solution seems to be use a watcher to watch $route and call a function on $route change

Upvotes: 0

haMzox
haMzox

Reputation: 2109

Vue can reuse the instance, when the component is same, so the this.$route in the component will change but created(), beforeMounted() and mounted() hooks won't be called.

To force vue to create a new component instance you can set a unique key on the like <router-view :key="$route.fullPath">

Another options is to react to changes in the $route with a watcher:

watch: {
  "$route.params.cname": {
    handler(cname) {
      // do stuff
    },
    immediate: true
  }
}

Upvotes: 1

Related Questions