Each time, vue-router instantiate a fresh Component instance

I have encountered a frustrating issue with vue-router that keeps bothering me. Every time I navigate between routes, a new instance of the component is created and the old instances remain active in the background!

My expectation was that when I switch to a new route, the old components would be destroyed or at least stop running.

Is there any workaround available to resolve this problem?

You can find a fiddle demonstrating the issue here: https://jsfiddle.net/4xfa2f19/5885/

let foo = {
    template: '<div>Foo</div>',
    mounted() {
        console.log('Mount Foo with uid: ' + this._uid);
        setInterval(() => {console.log('Instance ' + this._uid + ' of Foo is running')}, 500);
    }
};

let bar = {
    template: '<div>Bar</div>',
    mounted() {
        console.log('Mount Bar with uid: ' + this._uid);
        setInterval(() => {console.log('Instance ' + this._uid + ' of Bar is running')}, 500);
    }
};


const router = new VueRouter({
    routes: [
        { path: '/user/foo', component: foo },
        { path: '/user/bar', component: bar }
    ]
});


const app = new Vue({ router }).$mount('#app');

Answer №1

There are two ways you can tackle this issue:

Ensuring proper cleanup in the destroy hook

If you are utilizing external event listeners such as setInterval, addEventListener, etc., it is important to remember to properly remove them when your component is being destroyed. Here's an example:

{
    name: '...',
    template: '...',
    data() {
        return {
            interval: undefined,
            timeout: undefined
        };
    },
    mounted() {
        interval = setInterval(() => { console.log('Instance ' + this._uid + ' of myself is running') }, 500);
        timeout = setTimeout(() => { console.log('Instance ' + this._uid + ' of myself is running') }, 500);
        document.addEventListener('click', this.onOutsideClick);
    },
    beforeDestroy() {
        // Cleaning up interval
        clearInterval(interval);
        // Cleaning up any pending timeouts
        clearTimeout(timeout);
        // Removing any event listeners that are attached outside the root element
        document.removeEventListener('click', this.onOutsideClick);
    },
    methods: {
        onOutsideClick() {
            // Your logic here
        }
    }
}

Utilizing keep-alive to maintain component state

By using keep-alive, Vue stores your component and keeps it active in the background, ensuring only one instance exists at a time. However, be mindful that this approach may consume more memory if you have numerous routes.

<keep-alive>
    <router-view></router-view>
</keep-alive>

Answer №2

Every time I switch between my routes, a brand new instance of the component is generated.

This behavior is normal. You can maintain instances and reuse them using the <keep-alive> component, but this is usually not necessary and if it is, requires careful attention to reinitialize all local states of reused components when needed.

Creating a fresh instance is more straightforward and therefore the default setting.

Additionally, the previous instances are not deleted and continue running in the background!

This is unexpected. Previous instances should be destroyed.

setInterval(() => {console.log('Instance ' + this._uid + ' of Foo is running')}, 500);

Because this interval callback contains a reference to the component instance, it cannot be garbage collected by the browser. It is you keeping them alive, not Vue.

Without that interval, I would expect the instance to be removed by garbage collection after the router destroys them.

Answer №3

A similar problem is discussed over at: https://github.com/vuejs/vuex/issues/1580

One way to handle this is by using the out-in transition mode suggested by Rolandoda.

<transition mode="out-in">    <router-view></router-view> </transition>

Answer №4

Vue 3 has introduced some changes in syntax. To ensure that all components remain active in Vue Router, you can use the following solution:

<router-view v-slot="{ Component }">
    <keep-alive>
        <component :is="Component" />
    </keep-alive>
</router-view>

If you want to specifically keep one component alive, you can do so with this code:

<router-view v-slot="{ Component }">
    <keep-alive include="foo">
        <component :is="Component" />
    </keep-alive>
</router-view>

To prevent a specific component from being kept alive (while allowing all others to be), you can use the following code:

<router-view v-slot="{ Component }">
    <keep-alive exclude="foo">
        <component :is="Component" />
    </keep-alive>
</router-view>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Steps for triggering the material-ui menu to appear on hover of a button

I attempted to implement the following code without success. I was able to achieve it using plain CSS, but I need to utilize the makeStyles function provided by material-ui. My goal is to display a drop-down list of items when a user hovers over the butto ...

Combining Nuxt.js with Socket.io

While exploring the integration of socket.io with Nuxt, I stumbled upon this helpful resource: https://github.com/nuxt/nuxt.js/tree/master/examples/with-sockets Could someone shed light on why the io module is setting up a socketio server? Given that all ...

Trouble with Component Lifecycle (ComponentDidMount) activation while switching tabs in TabBar?

After implementing the react-native-tab-navigator library to navigate between components, I encountered an issue where the componentDidMount lifecycle method works only once. I have reached out for help by posting a query on Github and have also attempted ...

There seems to be a problem with the Chart property getter as it

I'm in the process of creating an object that corresponds to chartJS's line-chart model <line-chart :data="{'2017-05-13': 2, '2017-05-14': 5}"></line-chart> There is an API I utilize which returns a standard arra ...

Exploring the blur() function in JavaScript through cold calling

There is a specific line of code that I need help with. document.getElementById("firstName").addEventListener("blur", validateField); Additionally, there is this block of code: validateField = (event) => { const el = event.targe ...

Tips on utilizing index and eliminating React Warning: Ensure every child within a list has a distinct "key" prop

Hello, I am encountering an issue where I need to properly pass the index in this component. Can you help me figure out how to do that? Error: react-jsx-dev-runtime.development.js:117 Warning: Each child in a list should have a unique "key" prop ...

What is the best way to send an array of grouped data to a table

Here's how I organized the array: { "2023-10-01": [ { "emp_id": 1, "name": "Aruna", "code": "DO", "date": "2023-10-01" }, { &qu ...

Identifying text within clicked divs using identical ids

$(document).ready(function(){ $('#peoplelayer').click(function(){ $(this).fadeOut(500); var str = $(this).text(); alert(str); }); }); This is code where I use the same id "#peoplelayer" for all the divs. When on ...

can you explain the concept of a backing instance in react?

Although the concept of a "backing instance" is frequently mentioned in React documentation, I found it difficult to grasp its meaning. According to the React docs: In order to interact with the browser, you need a reference to a DOM node. By attaching ...

I must first log a variable using console.log, then execute a function on the same line, followed by logging the variable again

Essentially, I have a variable called c1 that is assigned a random hexadecimal value. After printing this to the console, I want to print another hex value without creating a new variable (because I'm feeling lazy). Instead, I intend to achieve this t ...

exploring the depths of nested objects and utilizing the 'for in

My issue involves receiving a json response from an API that includes objects within objects. It looks something like this: {Object}->{results}->{manyObjects} When I execute the following code: var list = data.results.list; for(val in list){ ...

Updating MySQL Status Using PHP and JavaScript

I have a list of tasks that users can add dynamically. Each task has a checkbox next to it, and when checked, the status of that task in the MySQL database should be updated. My initial approach was to include the following code: echo "<input type=&ap ...

JavaScript matching partial domains

let address = 'http://sub.domain2.net/contact/'; if (['https://sub.domain1.com/', 'http://sub.domain2.net/'].includes(address)) { console.log('match'); } else { console.log('no match'); } Here, it ...

Troubleshooting the issue with mocking API and creating a regular expression to match the dynamic part of a URL

I am struggling to create a mock for an API that includes dynamic parts in the URL. I attempted to use a regular expression, but it is not functioning as expected. The URL I am trying to mock is: https://example.com/programs/2fcce6e3-07ec-49a9-9146-fb84fb ...

Divide a JSON API object into segments within an express application

One way I'd like to organize my API's output is by splitting it into multiple pages. My idea is to access them using URLs like this: http://127.0.0.1:3000/api/articles/0/<API-TOKEN> This specific URL would display the first page containing ...

Instructions on how to automatically navigate to a different tab upon clicking an <a> element on a separate webpage, and subsequently display the designated tab on that

I have a button on my home page that, when clicked, should open a specific tab section on another page. The button is located on one page and the tabs are on a different page. On the second page, I have multiple tabs but will only mention one here, which ...

Tips for incorporating a value within the AngularJS select function

Having an issue with passing a list value in the html select method using AngularJS. Here is my code: app.js $scope.subcategory = function() { var query = "SELECT unit FROM Length;"; $cordovaSQLite.execute(db, query).then(function(res) { ...

I am still receiving an empty dropdown value despite implementing ng-selected

I am having issues with using ng-selected to retrieve the selected value from a dropdown. Instead of displaying the selected value, it appears blank. Here is the code snippet I have tried: <div> <select id="user_org" ng-model="selectedorg.all ...

Eliminating the table header in the absence of any rows

I have successfully implemented a Bootstrap table in my React application, where users can add or delete rows by clicking on specific buttons. However, I want to hide the table header when there are no rows present in the table. Can anyone guide me on how ...

When attempting to pass the `auth()->user()->name` from Laravel to a Vue template, an error occurs stating that it is not an object

Encountering an error when passing the auth()->user()->name to a vue template. Even after trying the meta method, the same error persists. It is confirmed that I am logged in to my system. Welcome.blade.php <script> window.user = @json( ...