Using Axios within nuxtServerInit() - vue.js

I need to get remote data to be displayed in every pages.
This call is perfomed in store/index.js:
export const state = () => ({
contact: {
hello: "World"
}
});
export const actions = {
async nuxtServerInit({ commit, state }) {
const { contactData } = await this.$axios.get("/contact");
commit("SET_CONTACT", contactData);
}
};
export const mutations = {
SET_CONTACT(state, contactData) {
state.contact = contactData;
}
};
Problem is that the value of contact turns to undefined in the store, whereas expected content is retrieved through Axios (the retrieved content is displayed in the SSR console...)
What am I missing here?

export const actions = {
async nuxtServerInit({ commit, state }, {app} ) {
const { contactData } = await app.$axios.get("/contact");
commit("SET_CONTACT", contactData);
}
};

Related

How I can call NuxtServerInit correctly?

When i try to call rest api with nuxtServerInit on Vuex store it don't call, but if call rest api on components or page it works.
store/index.js
import axios from 'axios'
export const state = () => ({
news: [],
})
export const mutations = {
SET_NEWS(state, posts) {
state.news = posts
}
}
export const actions = {
async nuxtServerInit({ commit }, ctx) {
const res = await axios.get('https://api/news.json')
commit('SET_NEWS', res.data)
},
}
export const getters = {
getNews(state) {
return state.news
}
}
pages/news/index.vue
computed: {
getNews() {
return this.$store.getters.getNews
}
}
Try calling your API like this in your vuex actions:
export const actions = {
async nuxtServerInit({ commit }, { req }) {
const res = (await this.$axios.$get('https://api/news.json')).data
commit('SET_NEWS', res)
},
}

in Vuex, How to load state and use data from the state when the application loads/renders first ?, I am using nuxt, Vue and Vuex as store

I am trying to load data from a JSON file into the VueX store, but the state does not get loaded until I try to refresh the VueX Store manually.
what I am trying to achieve is, before the app renders, the state should be loaded with the data.
Like before I access the homepage.
But I see on the Vue Devtools, that if set it to recording mode, then the app loads the data.
Below is code from store/index.js
//store/index.js
const exec = (method, { rootState, dispatch }, app) => {
const dispatches = [];
Object.keys(rootState).forEach(async (s) => {
dispatches.push(await dispatch(`${s}/${method}`, app));
});
return dispatches;
};
export const actions = {
nuxtServerInit(store, ctx) {
console.log('nuxtServerInit');
exec('init', store, ctx);
},
nuxtClientInit(store, ctx) {
console.log('nuxtClientInit');
exec('init', store, ctx);
},
init(store, ctx) {
console.log('nuxtInit');
exec('init', store, ctx);
},
};
store/app.js
//store/app.js
export const state = () => ({
config: {},
});
export const mutations = {
SET_CONFIG(state, config) {
state.config = config;
}
}
};
export const getters = {
config: (state) => state.config,
};
const loadConfig = ({ commit }) => {
const siteConfig = require('../config/data.json');
const appConfig = JSON.parse(JSON.stringify(siteConfig.properties));
commit('SET_CONFIG', appConfig);
};
export const actions = {
init(store, ctx) {
loadConfig(store);
},
};
Here the state is empty when the app loads. How can I access that when the app loads?
I normally call the init action of my store in the layout.
When this is too late you could also do it in a plugin, I guess.
You can use the context.store in the plugin.
// plugins/init.js
export default ({ store }) => {
store.dispatch("init")
}
// store/index.js
export actions = {
init(context) {
// ...
}
}

How do I get nuxtServerInit to dispatch an action on the Server?

I have a nuxt project using firebase. I want to use SSR and initiate and populate the store on SSR but I cannot get the code below to work.
I am working on a nuxt project I have a plugin/firebase project that initiates the firebase sdk. I have an asyncData function that works.
in my /store/index.js file I export the state function and the actions. In the actions I have the async nuxtServerInit that dispatches a `posts/getPosts' action passing the context.
In my store/index I have
export const state = () => ({})
export const actions = {
async nuxtServerInit({ dispatch }, context) {
await dispatch('posts/getPosts', context)
}
}
In my 'store/posts.js` I have
import { db } from '~/plugins/firebase'
export const state = () => ({
ActivePosts: []
})
export const actions = {
getPosts({ commit }) {
const postList = []
return db
.collection('posts')
.where('status', '==', 'approved')
.orderBy('CreatedAt', 'desc')
.get()
.then(docs => {
docs.forEach(doc => {
const newPost = doc.data()
newPost.id = doc.id
this.postList.push(newPost)
console.log(newPost)
})
})
.then(() => {
commit('addPosts', postList)
})
.catch(e => console.log(e))
}
}
In my firebase plugin I have
import firebase from 'firebase'
const firebaseConfig = {
apiKey: '<<correctkey>>.',
authDomain: '<<correctkey>>',
databaseURL: '<<correctUrl>>',
projectId: '<<correctid>>',
storageBucket: '<<correctbucket>>',
messagingSenderId: '<<correctkey>>',
appId: '<<correctkey>>'
}
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig)
}
export const db = firebase.firestore()
export const auth = firebase.auth()
This code, at least I thought, should initiate my store on the server and fill it with post values. When I check my store in vue developer tools there are no values in the store, although the getter is present and the state values(empty array) is present. This tells me that the store is initiated and the module is present, at least on the client side.
Turns out the problem was not with my action but the mutation. Here is the final code that got me to working.
import { db } from '~/plugins/firebase'
export const state = () => ({
ActivePosts: []
})
export const getters = {
getPosts(state) {
return state.ActivePosts
}
}
export const mutations = {
addPosts(state, payload) { // had to change { state } to state.
state.ActivePosts.push(payload)
}
}
export const actions = {
getPosts({ commit }) {
const postList = []
return db
.collection('posts')
.where('status', '==', 'approved')
.orderBy('CreatedAt', 'desc')
.get()
.then(docs => {
docs.forEach(doc => {
const newPost = doc.data()
newPost.id = doc.id
postList.push(newPost) //removed the `this.`
})
commit('addPosts', postList) //moved the commit to the // moved the commit out of its own then.
})
.catch(e => console.log(e))
}
}

How to get data into my Nuxt app for all pages/components

I have a file called config-ingest.js in my plugins directory with the following:
import gql from 'graphql-tag'
export default ({ app }, inject) => {
const client = app.apolloProvider.defaultClient;
const apps = gql`
query {
apps: allApps {
key
tree
}
}
`;
client.query({ query: apps }).then(response => {
inject('configStructure', response.data.apps);
});
}
Although the data is successfully retrieved, it doesn't seem to be available in all my pages and components.
If I want to get data from another server that should be available to all my pages, how would I do this? I want to stick this data in it's own file so I can get the data from any component or page when I please.
You should use the Vuex Store for that.
https://nuxtjs.org/guide/vuex-store/
I was able to do the following in store/index.js:
import gql from 'graphql-tag'
export const state = () => ({
apps: []
})
export const mutations = {
SET_APPS (state, apps) {
state.apps = apps
},
}
export const getters = {
getApps (state) {
return state.apps;
},
}
}
export const actions = {
async nuxtServerInit ({ commit }, { app }) {
const client = app.apolloProvider.defaultClient;
const apps = gql`
query {
apps: allApps {
key
label
tree
}
}
`;
await client.query({ query: apps }).then(response => {
commit('SET_APPS', response.data.apps)
});
}
}

Pre-fetch api data in Vuex with Nuxt.js

I am trying to pre-fetch some data and update Vuex before client-side kicks in.
store/index.js
export const state = () => ({});
export const getters = {};
export const actions = {
async nuxtServerInit ({ dispatch }) {
await dispatch('nasa/getImages');
}
};
store/moduleName.js
import fetch from 'node-fetch';
export const state = () => ({
images: []
});
export const mutations = {
storeImages(state, data) {
state.images = [];
state.images.push(...data);
console.log(state.images[0]); <- this logs in the terminal
}
}
export const actions = {
getImages(store) {
return fetch('api/url').then(response => {
response.json().then(function(data) {
store.commit('storeImages', data.collection.items.slice(0, 24));
});
});
}
}
My mutation gets triggered by nuxtServerInit and I am getting the first element logged in the terminal on page load. My store in the client-side however, is empty.
What am I missing?
With help from a friend we have managed to fix this issue by removing node-fetch and adding axios to Vuex instead.
The only change made was in store/moduleName.js which now looks like:
import Axios from 'axios'
export const state = () => ({
images: []
});
export const mutations = {
storeImages(state, data) {
state.images.push(...data);
}
}
export const actions = {
async getImages(store) {
let res = await Axios.get('api/url');
store.commit('storeImages', res.data.collection.items.slice(0, 24));
}
}