Home > front end >  Vue.js Uncaught TypeError: Cannot read properties of undefined
Vue.js Uncaught TypeError: Cannot read properties of undefined

Time:04-23

I am fairly new to Vue.js and having trouble understanding why I am getting this error:

Uncaught TypeError: Cannot read properties of undefined (reading 'contacts')

This is the method that is causing the error:

methods: {
    sortContacts: () => {
        return _.sortBy(self.contacts, [(contact) => {
            return contact.unread;
        }]).reverse();
    }
}

Contacts is an array in the component data, so why would it not be able to access this?

I am providing the whole script as per request, and here it is below this text. The code is written with Vue.js and I have not included the HTML above is this seems unnecessary.

<script>
import Conversation from "../components/Conversation";
import ContactsList from "../components/ContactsList";
import { mapState } from 'vuex';

export default {
    components: {Conversation, ContactsList},
    data() {
        return {
            selectedContact: null,
            messages: [],
            contacts: []
        }
    },
    computed: {
        ...mapState({
            userId: state => state.user.id
        }),
    },
    mounted() {
        axios.get('/api/contacts')
            .then((response) => {
                const contacts = response.data.data;

                this.contacts = _.sortBy(contacts, [(contact) => {
                    return contact.unread;
                }]).reverse();
            });
    },
    watch: {
        userId(userId) {
            Echo.private(`messages.${userId}`)
                .listen('NewMessage', (e) => {
                    this.handleIncoming(e.message);
                });
        }
    },
    methods: {
        addMessage(message) {
            this.messages.push(message);
        },
        async logout() {
            try {
                axios.post("/logout");
                this.$store.dispatch("logout");
                this.$router.push({ name: "auth-login" });
            } catch (error) {
                this.$store.dispatch("logout");
                this.$router.push({ name: "auth-login" });
            }
        },
        getMessages(contact) {
            this.updateUnreadCount(contact, true);
            axios.get(`/api/messages/${contact.id}`)
                .then((response) => {
                    this.messages = response.data.data;
                    this.selectedContact = contact;
                });
        },
        handleIncoming(message) {
            if (this.selectedContact && message.from === this.selectedContact.id) {
                this.addMessage(message);
            }

            this.updateUnreadCount(message.from_contact, false);
        },
        updateUnreadCount(contact, reset) {
            this.contacts = this.contacts.map((single) => {
                if (single.id !== contact.id) {
                    return single;
                }

                if (reset) {
                    single.unread = 0;
                } else {
                    single.unread  = 1;
                    this.contacts = this.sortContacts();
                }

                return single;
            });
        },
        sortContacts: () => {
            return _.sortBy(this.contacts, [(contact) => {
                return contact.unread;
            }]).reverse();
        }
    }
}
</script>

CodePudding user response:

I made a small snippet to make the same sort.

Beyond the obvious self mistake, I already change your sortContacts method notation to:

sortContacts: function () {
    return _.sortBy(this.contacts, [(contact) => {
        return contact.unread;
    }]).reverse();
}

And is working as expected.

var app = new Vue({
    el: "#app",
    data() {
        return {
        result: [{name: 'adam', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}],
        };
    },
    methods: {
        sortClick: function (){
            this.result = this.sortContacts();
        },
        sortContacts: function (){
            console.log(this.result)
            return _.sortBy(this.result, [(r) => {
                return r.name;
            }]).reverse();
        }
    },
});
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
  </head>
  <body>
      <div id="app">
        {{ result }}
        <button v-on:click="sortClick">Reverse</button>
      </div>
  </body>
</html>

Please, also verify the snippet const contacts = response.data.data; in you mounted section.

Normally the content of the request comes in the first data. Make sure your content really is in the second data attribute. A simple console.log in request will be fine.

  • Related