Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
147
rated 0 times [  149] [ 2]  / answers: 1 / hits: 17863  / 5 Years ago, thu, june 13, 2019, 12:00:00

When a user tries to directly navigate load a component url, an http call is made in my vuex actions, which will define a value in my state once it resolves.



I don't want to load my component until the http call is resolved, and the state value is defined.



For Example, in my component



export default {
computed: {
...mapState({
// ** this value needs to load before component mounted() runs **
asyncListValues: state => state.asyncListValues
})
},

mounted () {
// ** I need asyncListValues to be defined before this runs **
this.asyncListValues.forEach((val) => {
// do stuff
});
}
}


How can I make my component wait for asyncListValues to load, before loading my component?


More From » vue.js

 Answers
6

One way to do it is to store state values.


For example, if your store relies on single API, you would do something like this. However, for multiple APIs, it's a good idea to store each api load state individually, or using a dedicated object for each API.


There are usualy 4 states that you can have, which I prefer to have in a globally accessible module:


// enums.js
export default {
INIT: 0,
LOADING: 1,
ERROR: 2,
LOADED: 3
};

Then, you can have the variable stored in the vuex state, where the apiState is initialized with INIT. you can also initialize the array with [], but that shouldn't be necessary.


import ENUM from "@/enums";
// store.js
export default new Vuex.Store({
state: {
apiState: ENUM.INIT,
accounts: [],
// ...other state
},
mutations: {
updateAccounts (state, accounts) {
state.accounts = accounts;
state.apiState = ENUM.LOADED;
},
setApiState (state, apiState) {
state.apiState = apiState;
},
},
actions: {
loadAccounts ({commit) {
commit('setApiState', ENUM.LOADING);
someFetchInterface()
.then(data=>commit('updateAccounts', data))
.catch(err=>commit('setApiState', ENUM.ERROR))
}
}
});

Then, by adding some computed variables, you can toggle which component is shown. The benefit of using state is that you can easily identify the Error state, and show a loading animation when state is not ready.


<template>
<ChildComponent v-if="apiStateLoaded"/>
<Loader v-if="apiStateLoading"/>
<Error v-if="apiStateError"/>
</template>
<script>
import ENUM from "@/enums";
export default {
computed: {
...mapState({
apiState: state=> state.apiState
}),
apiStateLoaded() {
return this.apiState === ENUM.LOADED;
},
apiStateLoading() {
return this.apiState === ENUM.LOADING || this.apiState === ENUM.INIT;
},
apiStateError() {
return this.apiState === ENUM.ERROR;
},
})
}
</script>

aside... I use this pattern to manage my applications as a state machine. While this example utilizes vuex, it can be adapted to use in a component, using Vue.observable (vue2.6+) or ref (vue3).


Alternatively, if you just initialize your asyncListValues in the store with an empty array [], you can avoid errors that expect an array.


[#51999] Saturday, June 8, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
tyriquehenryq

Total Points: 248
Total Questions: 81
Total Answers: 105

Location: Bermuda
Member since Thu, Apr 20, 2023
1 Year ago
;