Ember component retains the state even after being destroyed

import Component from '@ember/component';
import { A } from '@ember/array';
import firebase from 'firebase';

export default Component.extend({
    classNames: ['flex-column', 'flex-column_h-center', 'layout-center', 'blog-list'],
    blogs: A([]),
    init() {
        this._super(...arguments);         
 console.log('BlogList component constructor. Length of blogs = ',  this.blogs.length);
    },

    convertFirebaseDataToList(data) {
        const dataArr = []
        Object.entries(data).map(([id, val]) => {
            dataArr.push({ id, ...val });
        });
        return dataArr;
    },

    fetchData() {
        const blogsRef = firebase.database().ref('blogs');
        blogsRef.once('value', snapshot => {
            const data = snapshot.val();
            const blogs = this.convertFirebaseDataToList(data);
            this.blogs.pushObjects(blogs);
        });
    },

    didInsertElement() {
        this._super(...arguments);
        this.fetchData();
    },

    willDestroyElement() {
        console.log('Destroyed');
        this._super(...arguments);
    },

});

This component retains the state even after it has been removed from the DOM.

This is the console output. This component is not used anywhere else. The only place its used is within blog-list route. When I click on a particular blog item link and come back to the blog-list by pressing back arrow or even a link which takes to the home route (blog-list route) this component gets rendered again but with the old data.

I think it’s because blogs is defined outside of the init hook. In classic components, when you create an object or an array in such manner, all instances of the component share the same object or array. If you have eslint-plugin-ember, it would give you a warning not to do so.

Can you try,

init() {
  this._super(...arguments);

  this.initializeBlogs();
},

initializeBlogs() {
  this.set('blogs', A([]));
},
3 Likes

I agree with @ijlee2! The blogs are being stored on the prototype instead of the instance. Using native ES6 classes make the correct thing to do easy, so I personally using them for this reason alone.

1 Like