Nuxt.js Loading data serverside with nuxtServerInit and Vuex - javascript

Currently i am working on storing data for a job opening application.
For the backend i use Laravel and for the frontend i use Nuxt.js
I am new to Nuxt, so i'm kinda stuck on the following issue.
I have a page for creating a new job opening called new-job.vue. I also created a store called jobs.js for handling the states.
On new-job.vue i have a form with data that has to be rendered in a list before the form starts.Like a list of all countries etc.. in order for me to select them in the form.
At this point i'm using asyncData within the export default on new-job.vue:
<script>
export default {
asyncData(context) {
return context.app.$axios
.$get('jobs/create')
.then(data => {
//context.store.dispatch('jobs/getTypes', data.types)
context.store.dispatch('jobs/getPlatforms', data.platforms)
context.store.dispatch('jobs/getCountries', data.countries)data.branches)
// return {
// loadedPost: { ...data, id: context.params.postId }
// }composer required barr
})
.catch(e => context.error(e))
},
computed: {
types () { return this.$store.state.jobs.types },
platforms () { return this.$store.state.jobs.platforms },
countries () { return this.$store.state.jobs.countries },
},
}
The asyncData method works and the lists of types, platforms and countries are getting filled with data from the database and the state from the Vuex store gets updated. .Only the data is being rendered on the client side.
I prefer this data to be loaded server side, so i was looking at nuxtServerInit. Only can someone explain to me how i can make this happen.
I placed an async call inside the export default of new-job.vue:
async nuxtServerInit ({ commit, state }, { app }) {
let res = await axios.get(`jobs/create`)
console.log(res)
commit('setPlatforms', res.data.platforms)
commit('setTypes', res.data.types)
commit('setCountries', res.data.countries)
},
I created the commits in the mutations of the jobs.store, but the states are not being updated.
What am i doing wrong and/or what am i missing?
Or maybe another question, is nuxtServerInit the way to go? Or is loading these lists of data on the clientside not a big deal?
UPDATE:
I use modules mode for the store, so i created a store called jobs.js. Inside this file i tried to call nuxtServerInit as well, but i didn't get any response.
nuxtServerInit(vuexContext, context) {
return context.app.$axios
.$get('jobs/create')
.then(data => {
console.log(data)
})
.catch(e => context.error(e))
},

From nuxtServerInit API reference in Nuxt.js documentation:
If the action nuxtServerInit is defined in the store, Nuxt.js will call it with the context (only from the server-side).
In other words, it is a reserved store action available only in store/index.js file and if defined will be called on server-side before rendering requested routes.
Only asyncData and fetch methods are available within pages.

Related

How to use manual cache updates using RTK Query

I have recently started working on redux toolkit, Basically i want to refetch the data from database if there is mutation. I am using flatlist in my react native project where on pull to refresh i want my "getPosts" endpoint to refetch and get updated.
Note: I know about using tags for automated cache invalidation. but on web RTK query is not implemented.
Talking about pessimistic update:
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
try {
const { data: updatedPost } = await queryF`enter code here`ulfilled
const patchResult = dispatch(
api.util.updateQueryData('getPost', id, (draft) => {
Object.assign(draft, updatedPost)
})
)
} catch {}
},
just give a help how to call this function from APP.JS or anywhere from the app. Thanks
You can just call refetch, you don't need anything that complicated. See the docs on useQuery
const myResult = useMyquery(args)
// in your pull to refresh trigger:
myResult.refetch()
If you are outside of a component, you can also still
store.dispatch(api.endpoints.myEndpoint.initiate(args, { track: false })))
to trigger a refetch

Page not loaded on refresh using vuex and getter

Trying to solve page refresh issue that occurs using vuex and getters. I must be missing something on how the reactivity works, but haven't been able to identify what after searching around and reading vue pages on reactivity.
As an example, I have a component that will initially load just fine:
Create lifecycle dispatches action to retrieve data from API and push to array in state
Computed property in component retrieves data using getter (filter array to specific person)
Component displays a few properties in array
When page is refreshed it seems that the action is called again and data retrieved but it doesn't seem like the getter works correctly to get the new data and page does not load. If I test accessing the data in the state directly then refresh works fine. So it seems that the data is properly loaded to the state when refreshing but the getter somehow doesn't have it?
Appreciate any help!
Component:
<script>
export default {
props: ["id"],
computed: {
player() {
return this.$store.getters["player/getPlayerById"](this.id);
}
},
created() {
this.$store.dispatch("player/fetchPlayer", this.id);
}
};
</script>
getter:
getPlayerById: state => id => {
return state.players.find(plr => plr.PlayerID === id);
}
action:
var promise = EventService.getPlayer(id)
.then(response => {
commit("ADD_PLAYER", response.data);
})
ADD_PLAYER mutation:
ADD_PLAYER(state, player) {
state.players.push(player[0]);
}

NextJS: Do I need to use getInitialProps with next-redux-wrapper to share state to all pages?

I'm using next-redux-wrapper and dispatching actions from getServerSideProps from individual pages. But I realized that I can't access the populated store state from another page. If I try to, in either client-side or server-side, the state returns empty in the other pages.
So, I heard that using getInitialProps is required to share state among all pages. Since I'm getting confused with all these I want to have some doubts cleared. I want to know:
When is it necessary, if at all, to use getInitialProps in the _app.js file when using redux with next-redux-wrapper? I heard that need to use getInitialProps inside _app.js in order to make the state accessible to every pages. But it's not working for me. Maybe due to wrong implementation!
If I use getInitialProps in _app.js then, is it not required to use getServerSideProps or getStaticProps in individual pages?
After populating state with getServerSideProps, can I share the state to every page without using getInitialProps in _app.js or if nneded can I pass the fetched state to getInitialProps in _app.js?
Yes, You have to use getIntitprops in the APP component to provide store in all pages in this case all page will run on a server which huge downfall, if you have lots of static pages,
or you can use this code on each page according to your needs but your dispatch will change server-side state only!!!, which means you can access them on the client-side.
export const getServerSideProps = wrapper.getServerSideProps(async ({ store, query }) => {
try {
const { id } = query
const res = await api.get('/abc', { params: { id } })
await store.dispatch(action)
return {
props: {
id,
data: res.data,
isServer: typeof window === 'undefined',
}
}
} catch (error) {
return {
props: {
errorCode: 409,
message: "Data Unavailable"
}
}
}
})
In the end, I ditched both options because it provides a bad user experience.
My recommendation is to use getInitProps and check if the page is rendering on the server then call API and save props in client-side, otherwise call API in the client a and save it.

Vue JS, how to make axios request API running first before HTML DOM component loaded?

I'm still learning this VueJS with Laravel, what I want to do is to get the categories data from API and load it into the select dropdown, but I found that this Axios request running too long.
here's the snippet code
export default {
data() {
return {
category: 0,
categories: [],
loading: true,
}
},
async created() {
let uri = '/api/getCategory';
axios.get(uri).then(response => {
this.categories = response.data;
console.log('2');
}).catch(error => console.log(error))
.finally(() => {
this.loading = false;
});
console.log('1');
},
methods: {
loadCategories() {
axios.get('/api/getCategory')
.then(response => this.categories = response.data)
.catch(error => console.log(error));
}
}
}
based on this.
1
DOM LOADED
2
is there a way to make my Axios API request to fetch the data first before the HTML finish loaded?
You cannot access reactive data before the created hook. Axios is made up for reactive processing which means once the data are available they will be displayed.
The solutions I am suggesting are the below :
You could request the data on a parent component and store it in localStorage for example. You could use it anywhere in the application then.
Keep your code in the created hook. Use a computed property instead of categories for instant rendering.
computed:{
computedCategories(){
return this.categories;
}
}
You definitely have to check your server side code for query enhancement.
If you're not able to reduce the response time of the request, I suggest you implement some kind of visual loading indication, maybe on the select input. Could be a spinner or a small "Loading..." text.
Having the request in a parent component for example, won't make up for the fact that the request response time is slow and will be a bad experience for the user, with no indication that the component is loading/fetching data.
If the problem is that you get render errors, because categories is not yet available to the DOM, you can use a conditional render v-if="categories.length", to only render the elements with data, when it's available.

How to rework an Angular1 App to a VueJs app

So I'll get right to it :
I'm trying to remake an existing app that used Angular 1 , instead using VueJS 2.
Being unfamiliar to Angular1 I find it challenging to decide on a few things :
1.What are factories(probably services), where do I place/write manage them?
2.Okay I know angular is big on controllers, but I cannot seem to understand if I were to use Vue , what's the alternative to the controller, and where to hold the code.
So, basically what I've gotten so far is to use VueX for state management and I have moved some services there, however - I can't figure out for example if a certain service #requires 'NameOfOtherService' , does it mean it imports it like in NodeJS const NameOfOtherService = require ('insert/path/here'); ?
Basically the app gets data from an API and php scripts, for example :
In the angular 1 version in my appsettings, which is using an AppConfig module I have a pathFromScript(script) => {} // etc.
My question is , how do I manage EVERYTHING that's going on within one app like that translated to Vue?
Thank you in advance I know it's entirely a shot in the dark here.
Yours truly ,
As for Vue.Js, your angular controllers are methods. If you need to get some data from an API, you can use a method to call a Vuex action and either return the value back to the method or add it to your state, so it's available everywhere. This will look like the example below.
I guess your factories / services are managing API calls. I would place that inside Vuex with axios to make API calls.
Methods is the same as controllers in Angular. You create methods on the specific page. If you need a method to be resused multiple places, you can use mixins. Mixins extends the specific page by importing it. You can read about it here: https://v2.vuejs.org/v2/guide/mixins.html
page.vue
{{data}}
export default {
import { mapActions, mapGetters } from 'vuex'
...
computed: {
...mapGetters({
data: 'getData'
})
},
methods: {
...mapActions({
getServerData: 'getDataFromServer'
})
},
created () {
this.getServerData()
}
}
store.js (vuex)
import axios from 'axios'
state: {
data: null
},
getters: {
getData: state => {
return state.data
}
},
mutations: {
setDataFromServer: (state, payload) => {
state.data = payload
}
},
actions: {
getDataFromServer: ({ commit }) => {
return axios.get('https://website.com/api/data').then((response) => {
commit('setDataFromServer', response)
})
}
}
In this example the created is calling the vuex action to get the data from the server. When the server returns the value, it calls a mutation which sets the response in a state (data). The mapGetters which calls the getters in vuex, returns the data from state. It updates whenever the state changes.
Hope this makes sense

Categories