Fetching global api data in nuxt - vue.js

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)
}
}
}

Related

Initate Session on page load

I have a requirement where I need to set Global Axios header and refresh session(Calling multiple Api's). In vuejs we would have a App.vue which is the entry point for our application we would do these types of processing in that.
App.vue
export default {
async created(){
await this.$store.dispatch('initateSession');
}
}
The benefits of doing this is that this is called only once(not on every route change), and on every page load, I am looking to implement the same functionlity in Nuxt.
Now as we dont have any App.vue in case of Nuxt one solution that i could think off is to create a middleware for this , which can work but that will be called on every route change I dont want that, does anyone know any workaround for it?
Instead of middleware you can create a plugin:
plugins/session.js:
window.onNuxtReady(() => {
// Do something
})
And then add it to the plugins section inside nuxt.config.js.

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
...

how to load the data from the auth module of nuxtjs in a component

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.

Nuxt.js: Managing CMS collections for a statically generated website

On nuxt generate, we need to fetch all collections from the CMS. Since our website is completely static, it should be sufficient to fetch every collection only 1 time, and then make them available to all routes.
We run into issues making this happen, without exposing all our websites content to every single route.
We could use vuex to store all the content. However, we don't want a giant store object with all our websites content to be available to the client. Only during the build process, the server should have access to it and pass the content needed to every single route, eg. via asyncData()
(remember, we have a statically generated website, therefore asyncData() is never called from the client).
Example: We need the blog collection on /blog, but also on /blog/:slug, and on /press. Currently we fetch them individually:
// /pages/blog/index.vue
export default {
asyncData() {
return fetchArticles();
}
}
// /pages/blog/_slug.vue
export default {
asyncData(context) {
// made available in nuxt.config.js
return context.payload;
}
}
// nuxt.config.js
export default {
generate: {
// generate dynamic routes
routes: async function() {
const collection = await fetchArticles();
const result = collection.map(item => {
return {
route: `/blog/${item.slug}`,
// save in payload, to make available in context
payload: item
};
});
return result;
}
}
}
Problem: We are fetching the same collection twice. We want to fetch it once, and then make it available to all routes.
Expected result: Being able to
fetch every collection only 1 time
storing all the collections on the server side only, passing needed content to routes via asyncData()
on client side, not being able to access that "server-side-store"
Actual result:
having to refetch the same collection for several routes
Just fill your /blog/index.vue the same way as your single blog post, with payload.
You only need to make sure to exclude /blog path from list of static routes. You can try this https://github.com/nuxt/nuxt.js/issues/2719#issuecomment-508583281. Or make nuxt build && nuxt generate --no-build command (this way all static routes will be excluded, you'll need to specify them manually).
PS:
because context.payload is only available to the dynamic routes
I have just tried the method above and it worked.

created hook for vuex / nuxtClientInit?

I was wondering whats the best way to do something like nuxtClientInit. I'm trying to load the Auth State as early as possible on the client and save it in my vuex store but not on the server side. It would be great if vuex had something like the created hook for components but that doesn't exist to my knowledge.
How could I achieve this behavior? One way could be calling an action from a layout but is that the best way?
I understand the nuxt team are working on a nuxtClientInit feature but before they release that you could just make your own. To understand the workflow that nuxt undertakes when there is a request you can look at the lifecycle here. This shows that nuxtServerInit is called first then middleware. During this middleware call nuxt.config.js is served and this contains your custom configuration. Part of this is 'plugins' which as the docs say,
This option lets you define JavaScript plugins that should be run
before instantiating the root Vue.js application.
So if you write a plugin to call a store action you can then get and set your local storage from there. So, start with a nuxt-client-init plugin:
//nuxt-client-init.client.js
export default async context => {
await context.store.dispatch('nuxtClientInit', context)
}
then add the plugin to nuxt.config.js:
//nuxt.config.js
plugins: [
'~/plugins/nuxt-client-init.client.js'
],
If you notice the naming convention here, the .client.js part of the plugin tells nuxt this is a client only plugin and is shorthand for '{ src: '~/plugins/nuxt-client-init.js', mode: 'client' }' which since nuxt 2.4 is the way to define the old '{ src: '~/plugins/nuxt-client-init.js', ssr: false }'. Anyway, you now have a call to your store so you can have an action to call from local storage and set a state item.
//store/index.js
export const actions = {
nuxtClientInit({ commit }, { req }) {
const autho = localStorage.getItem('auth._token.local') //or whatever yours is called
commit('SET_AUTHO', autho)
console.log('From nuxtClientInit - '+autho)
}
}
You probably need to restart your app for that to all take effect but you are then getting and using your Auth State without any of that pesky nuxtServerInit business.