Vuejs synchronously requests rendering data

I have a one page application that requires authentication. When the user has been authenticated, then go to some pages or click the reload button in the browser, he will ask api to provide his authentication data. then I have this error:

[Vue warn]: Error when evaluating expression "auth.name": TypeError: Cannot read property 'name' of null (found in component: <navbar>)

This error is caused by vue displaying auth data while the api request has not yet completed.

Can vue wait for an api request to complete the first before vue render auth data strong>?

more clearly what is happening here. Here is the code:

 // main.js import Vue from 'vue' import App from './App.vue' // root vue import store from './vuex/store' // vuex import router from './router' // my router map sync(store, router) router.start(App, '#app') // end main.js // App.vue <template> <main> <div class="wrapper"> <router-view></router-view> </div> </main> </template> <script> import authService from './services/auth' // import authservice ready () { // here is code that should be done first before vue render all authData auth.getUser((response) => { self.authData = response }) }, data () { return { authData: null // default is null until the api finish the process } } </script> // end App.vue // SomeRouterComponents.vue <template> <!-- some content --> <div> // always got error: cannot read property 'name' of null // here I expect to render this after api has been resolved {{ $root.authData.name }} </div> <!-- some content --> </template> 
+6
source share
3 answers

The problem you were talking about is that you are trying to access an object that is not there, and due to an error, Vue cannot display it in the next tick. The solution is to use simple v-if to verify data loading, this only works for reactive data.

root component

  import auth from './services/auth' // import authservice ready () { // here is code that should be done first before vue render all authData auth.getUser((response) => { self.authData = response self.dataReady = true }) }, data () { return { authData: null, // default is null until the api finish the process dataReady: false } } 

otherComponent

  <div v-if="dataReady"> // note that if you use v-show you will get the same error {{ $root.authData.name }} </div> <div v-if="!dataReady"> // or some other loading effect Loading... </div> 

I used v-if="!dataReady" instead of v-else because it will be deprecated in Vue 2.0

+10
source

You can simply prevent Vue from trying to access the property of the object, for example:

 {{ $root.authData ? $root.authData.name : null }} 

In some cases, you can even change null for the Loading... message.

+2
source

You can use the data transition hook parameter with the waitForData option waitForData :

 <script> import authService from './services/auth' export default { route: { waitForData: true, // wait until data is loaded data (transition) { authService.getUser((response) => { transition.next({ authData: response }) // set data }) } }, data () { return { authData: null } } } </script> 

In addition, if you do not want to use this parameter, you can check whether the data is loaded using the $loadingRouteData property.

More details here: http://router.vuejs.org/en/pipeline/data.html

+1
source

All Articles