how to load the data from the auth module of nuxtjs in a component - vue.js

I am trying to access the data that is in #nuxt/auth in a component, however when I log in and the component loads it does not show the requested data but when refreshing the page if it shows the data.
what would be the ideal way to load this data, for now I am doing so:
computed: {
user() {
return this.$auth.user;
},
},

$auth doesn't change reactively without new requests to the backend, so computed is not the best place. Using asyncData or fetch to set this object to a simple data or state seems better, or even use directly $auth.user.

Related

Nuxt.js footer component is not executing code to retrieve data

We have a nuxt.js application which retrieves data from strapi. this works for all the other pages that we've created, but when we try to retrieve data for the <Footer /> it appears that the code is not executing.
This is the code that we use for retrieving on the index page:
export default {
async asyncData({ $strapi }) {
return {
homepage: await $strapi.find("homepage"),
};
},
}
All we change from page to page is the variable name and the value its finding.
This works on 10 - 12 pages.
On main pages we are able to retrieve the data of the footer with this code:
export default {
async asyncData({ $strapi }) {
return {
footer: await $strapi.find("footer")
};
},
}
However when we put this code in our footer component it doesn't appear to execute, as no variable was shown in the view explorer, and if we try an render anything form the {{footer}} then we get an error saying we've referenced something that doesn't exist.
Is there any reason why this code isn't executing in the footer component?
The asyncData hook can only be used on page components. The official documentation explains how you can work around this issue:
asyncData is only available for pages and you don't have access to this inside the hook.
Use the new fetch hook that is available in Nuxt 2.12 and later versions.
Make the API call in the mounted hook and set data properties when loaded. Downside: Won't work for server side rendering.
Make the API call in the asyncData method of the page component and pass the data as props to the sub components. Server rendering will work fine. Downside: the asyncData of the page might be less readable because it's loading the data for other components.

Fetching global api data in nuxt

I'm starting Nuxt project and I have to fetch basic data from my backend.
for example language dictionary or some data for leftbar and etc.
in Vue I can just call everything I need in App.vue and save it in vuex and then use whenever I want, but with Nuxt every page is different and I'm curious where should i call this global data api calls.
I'm guessing I have to create middleware and call actions if data is not loaded already or there is better solution?
You mention it's global data and you're using universal mode- I think you're looking for nuxtServerInit(). This store action runs once on the server, before created, mounted hooks etc. You can use it to populate your store with data that your components (including pages) rely on.
Take a look at the docs.
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}

Load async data into the vuex store when Nuxt app loads

I am trialling a project in Nuxt. Liking it so far except I am a little confused as to how to load data from an external async service so that it is available in Vuex from the very first route.
I have tried adding middleware on the default layout to dispatch the store action but I do not see the service being called straight away. Only when I navigate deeper into the routes do I see the action dispatched.
I did something similar in a standard Vue project and added the created method to the App.vue.
Is there a similar way in Nuxt?
What you need is called a fetch.
The fetch method, if set, is called every time before loading the component (only for page components). It will be called server-side once (on the first request to the Nuxt app) and client-side when navigating to further routes.
Warning: You don't have access of the component instance through this inside fetch because it is called before initiating the component.
async fetch({ store }) {
await store.dispatch('your-action')
}
If you need parameter:
async fetch({ store, params }) {
await store.dispatch('your-action', params.id)
}
I gave an example of id. The name of the parameter depends on the name of your page.
_id => params.id
_slug => parmas.slug
...

Nuxt.js with vuex-persist - persisted state not available in asyncData upon page refresh

Upon first page refresh, the asyncData function is not able to fetch the persisted state. When I follow another NuxtLink, and go back to this page, while the state is not mutated in the meantime, the data is there. This means the persisted state is not available on the server side at first load/refresh. LocalStorage is where I choose to persist the relevant state items.
A pages component that uses asyncData:
asyncData({ app, params, store }) {
//its not available upon first refresh, but is after following a random nuxtlink and going back
const cartProducts = store.getters.getCartProducts
},
store/index.js is straightforward. Unfortunately, the state is completely empty in asyncData upon first page refresh.
getCartProducts(state) {
return state.cart.products
},
vuex-persist.js imported properly with mode 'client' as recommended in the Github Readme
import VuexPersistence from 'vuex-persist'
/** https://github.com/championswimmer/vuex-persist#tips-for-nuxt */
export default ({ store }) => {
window.onNuxtReady(() => {
new VuexPersistence({
key: 'cartStorage'
/* your options */
}).plugin(store)
})
}
How can I make sure the relevant store terms from local storage are persisted before asyncData is called?
You can't do this. Its impossible. There is no localstorage on server. And asyncData executed on server on first load/refresh. So there is no way to get data from in asyncData from localstorage on server even theoretically.

vuejs component created wait for data to load first

I have an App.vue component where I want to load the currently logged in user. I also want to redirect the user when he\she tries to go the login route and the currently logged in user is already saved in context (he's already signed in).
// inside App.vue component
created() {
AuthService.getCurrentUser().then((user) => {
this.user = user;
});
}
I have a check in the created method of the login component for whether the currentUser is setted, but then when the user tries to go to the login page it might be possible that the the request for the current user is not finished.
My question is:
How do I wait for the data to load before the App.vue component loads?
I saw something like this:
waitForData: true,
data(transition) {
return AuthService.getCurrentUser().then(currentUser => {
transition.next({ currentUser });
});
}
which doesn't actually wait for the data to be loaded and the component loads anyway.
Edit: I'm aware of beforeRouteEnter but this is App.vue component which is a parent component of all components and not a route specific component.
I ran into a very similar problem and solved by adding a v-if on the element that wrapped the child component that depends on the loaded data. And then of course have an data property to control that v-if. If you don't have a wrapping element you can always use a template element to do the wrapping.
This is not the Vue way of doing things.
Use VUEX to store your currentUser object
Set up the Vuex getters in App.vue's computed section. Your template will be updated dynamically once the data is ready.
See the mapGetters section in this page. It works very well with the computed mechanism.
You can also use v-if in your relevant component, so that the component won't be created before your data is ready in VUEX.
If using vue-router, you can use the beforeRouteEnter guard to load data async, as described here: https://router.vuejs.org/en/advanced/data-fetching.html
One way I can think of is when the user is loaed in the App.vue component to check the current path and if it's \login to redirect.
Something like this:
created() {
AuthService.getCurrentUser()
.then(user => this.setCurrentUser(user))
.then(() => {
const { path } = this.$router.currentRoute;
if (path === '/login') {
this.$router.push('/');
}
});