Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vuex getters in computed properties showing undefined until full page load

I'm trying to create computed properties using data pulled with the mapGetters function in vuex, but I'm always getting undefined, until the page/dom fully loads.

Here's an example for an isRegistered computed property that I use to hide/display certain buttons.

computed: {
      ...mapGetters(['solos', 'user']),
      isRegistered () {
        return this.solos.registered.indexOf(this.user._id) !== -1
      }
}

Here is the HTML for buttons that use the isRegistered computed property.

<a href="#" class="register-button" v-if="!isRegistered">REGISTER NOW</a>
<a href="#" class="registered-button" v-if="isRegistered">REGISTERED</a>

I'm setting the getters via an action which I'm calling in the created function

created () {
      this.getTournament('solos').catch(err => {})
}

Here's my action for setting the corresponding getters

getTournament: ({commit}, type) => {
    return feathers.service('tournaments').find({
      query: {
        type: type,
        status: 'registering'
      }
    }).then(tourney => {
      commit(type.toUpperCase(), tourney.data[0])
    })
}

Here's the corresponding mutation

const mutations = {
  SOLOS (state, result) {
    state.solos = result;
  }
};

Here's the corresponding getter

const getters = {
   solos (state) {
     return state.solos
   }
}

The issue I'm having is the value is initially showed as undefined until the PAGE/DOM is fully loaded, causing .indexOf to throw the following error:

TypeError: Cannot read property 'indexOf' of undefined

The only way I've been able to get this to work is to use an if statement on the computed property that checks if the state data has loaded yet.

isRegistered () {
  if (this.solos._id) return this.solos.registered.indexOf(this.user._id) !== -1
}

This doesn't seem like a proper way of doing things. What am I doing wrong?

like image 298
Jayson H Avatar asked May 25 '17 17:05

Jayson H


People also ask

Is Vuex getter cached?

Vuex allows us to define "getters" in the store. You can think of them as computed properties for stores. As of Vue 3.0, the getter's result is not cached as the computed property does.

Are Vuex getters reactive?

Vuex getter is not reactive.

How do you use getters and setters in Vuex?

The action will commit a mutation to update the state. You can't update state directly, it needs to be handled via a mutation. To access the state, we can use a getter to fetch the current user's name. To have that name update in the Vuex store we then need to use a setter which will dispatch an action.

What is the use of Mapstate in Vuex?

Mapping in Vuex enables you to bind any of the state's properties, like getters, mutations, actions, or state, to a computed property in a component and use data directly from the state. Although we can get the job done with this. $store.state.user.data.name , we can use a map helper to simplify it to this.


1 Answers

The issue is probably about the vue lifecycle.

At the created hook, the computed properties, watchers and data of component are initialized (runs synchronously), but solos getter runs inside a promise (runs asynchronously), so the lifecycle continue without the promise get done.

When created hook is finished, the watchers was created, which means if data get changed, they will be reflected at the DOM, but only after the promise returns the result, the solos will be filled. So at the initialization of the app, the promise is not ended, but as soon it ends the data is updated and displayed.

A way to avoid this error is to use v-if="solos.registered", but I'm still searching for a better way to solve this.

like image 76
tomrlh Avatar answered Oct 03 '22 12:10

tomrlh