Skip to content

VueJS InertiaJS Uncaught (in promise) TypeError: Cannot read property ‘search’ of undefined

I’m implementing on Vue JS with Inertia a list where you can filter by name

data() {
        return {
            selectedUser: this.value,
            selected: null,
            search: '',
        }
    },

computed: {
        userlist: function(){
            return this.users.filter(function(user){
                return user.name.toLowerCase().match(this.search.toLowerCase())
            });
        }
    },

and the component

<input class="form-input" placeholder="Search.." v-model="search">
<a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-900 flex items-center" v-for="user in userlist" :key="user.id" @click.prevent="select(user)">

However, when I open the modal, where the component is, I get an error

Uncaught (in promise) TypeError: Cannot read property 'search' of undefined

I’ve already hardcoded the search value, like this

computed: {
        userlist: function(){
            return this.users.filter(function(user){
                return user.name.toLowerCase().match('John')
            });
        }
    },

and the component renders just fine. I’m not getting where the error could be, so any help would be appreciated

Answer

The problem PROBABLY is that you’re using the this keyword expecting it to be a reference to your component instance, but you’re using it inside a function declaration, which creates a new context, causing this to be undefined.

computed: {
    userlist: function(){
        // here, this is the component instance
        return this.users.filter(function(user){
            // --> function(user) { creates a new context
            // here, this is undefined and this.search will cause the error
            return user.name.toLowerCase().match(this.search.toLowerCase())
        });
    }
}

To prevent this, you can use an arrow function, which will will keep the existing context. This means that the this keyword will still reference your component instance.

computed: {
    userlist: function(){
        // here, this is the component instance
        return this.users.filter((user) => { // --> replaced function with an  arrow function
            // here, this is still a reference to the component instance
            return user.name.toLowerCase().match(this.search.toLowerCase())
        });
    }
}