I am trying create a to fetch data from the server and show them to the user. But the issue is that nothing apart from the dummy information is displayed.
Basically there are two scenarios:
1. Navigating to the page from some other link (This works as expected)
Explanation: Such as going from http://localhost:3000/ to http://localhost:3000/assignments/explore and it renders all the fetched contents as expected.
Vue plugin ss
2. Entering the page directly through the url or press refresh
Explanation: By directly typing http://localhost:3000/assignments/explore in the url nothing is displayed apart from the dummy card
Vue plugin ss
As you can see the length of the assignment state is 1 instead of 3 and the vuex action saveAssignments is also missing in this case
Template tag in explore.vue
...
<div v-for="assignment in assignments" :key="assignment._id">
<Card :assignment="assignment"></Card>
</div>
...
Script Tag in explore.vue
fetch() {
this.$store.dispatch('assignment/fetchAssignment')
},
computed: {
assignments() {
return this.$store.state.assignment.assignments
},
},
assignment.js //Vuex Store
export const state = () => ({
assignments: [ //dummy data
{
_id: '5f1295181ebf00dd0070de1',
title: 'dummy',
Description: 'asfd',
Price: 50,
createdAt: '2020-07-18T06:22:09.037Z',
updatedAt: '2020-07-18T06:22:09.037Z',
__v: 0,
id: '5f12951081ebf00dd0070de1',
},
],
})
export const mutations = {
saveAssignments(state, newAssignments) {
state.assignments = state.assignments.concat(newAssignments)
},
}
export const actions = {
async fetchAssignment({ commit }) {
const data = await this.$axios.$get('assignments')
commit('saveAssignments', data)
},
}
Any help will be appreciated
Found the solution
I just had to add the return statement before the dispatch function in fetch()
fetch(){
return this.$store.dispatch('assignment/fetchAssignment')
}
Found my answer here
Nuxtjs async await in a page doesnt work on page refresh
Related
I have a page with a lot of inputs where the user can change the details of an event and after that the user can click on the save button which would trigger the saveChanges() method which would re-render the page with the new inputs. This would be only a mock implementation for now as the backend is not ready so if there would be a full page reload the changes would disappear.
I store the changes in my store.state and would like to see if there is a store.state.newEvent in my preloader if there is then the params.event should be the store.state.newEvent if not then the original event object.
data() {
return {
event: this.$route.params.event,
newEvent: { ...this.$route.params.event},
...
};
},
saveChanges() {
store.setNewEvent(this.newEvent);
this.$router
.push({
name: RouteNames.EventManagement.name,
params: {
ID: this.event.id,
},
});
},
my router
const routes = [
{
name: RouteNames.EventManagement.name,
path: RouteNames.EventManagement.path,
beforeEnter: async to => {
await managementPreload.preload(to);
},
component: EventManagement,
},
]
my preloader
async preload(to) {
store.showSpinner();
console.log(store.state.newEvent);
if (store.state.newEvent) {
to.params.event= store.state.newEvent;
} else {
let data = await EventManagementManager.getById({
id: to.params.ID,
});
to.params.event= data.event;
}
store.hideSpinner();
return to;
}
When I try to call the saveChanges() the console.log does not even get triggered so I guess the program does not get to the preloader at all.
I have one query and one subscription, what I am trying to do is add my data to previous query so that it shows the full list.
I have one query which is returning me list of students and I am rendering that on UI like below
function Test(props) {
const { loading, data: dta } = useQuery(GETSTUDENTS);
const { data: d } = useSubscription(GETSUBSTUDENTS, {
onSubscriptionData: ({ subscriptionData: { data } }) => {
let fname = data.getSubStudent.fname;
let lname = data.getSubStudent.lname;
dta.getStudents.push({ fname, lname });
},
});
return (
<div className="">
{dta &&
dta.getStudents.map((li) => {
<div>
<p>{li.fname}</p>
<p>{li.lname}</p>
</div>;
})}
</div>
);
}
export default Test;
But the main issue is the above one is not updating the cache so when I change the routes and come bqack again it takes the previous data only.
So What I wnat to know na what is the best way to do this, I have check subscribeToMore also but did not get idea How to implement that and how it works with hooks.
I am getting some data from subscription and on that basis I want to change some other part so can I use refetchQueries I did not found any good tutorial which uses hooks (react-apollo-hooks) using qraphql
First, you can just use the pooling option of the useQuery instead of subscription,
I suggest you check it.
From Apollo docs:
"In the majority of cases, your client should not use subscriptions to
stay up to date with your backend. Instead, you should poll
intermittently with queries, or re-execute queries on demand when a
user performs a relevant action."
Apollo subscription
If you still want to use the subscription I think you should use the subscribeToMore and to update your cache policy inside the apollo cache file:
const cache = new InMemoryCache({
typePolicies: {
Agenda: {
fields: {
tasks: {
merge(existing = [], incoming: any[]) {
return [...existing, ...incoming];
},
},
},
},
},
});
You can read more about it here: merge cahce
And check that video: youtube apollo cache
I am using vuex in nuxt and I get user data after user login, and store the data in vuex.
When I display the data in another page as computed property with getters, everything works fine and it displays user data except for img tag.
When I try to display user icon with url which is stored in vuex, it works for the first time, but when refresh the page, it gets the data before the user data is stored for some reason...( but the another data still renders user data properly) and of course, icon does not render.
Plus, if I just display the url of icon from vuex as strings in div, it shows icon url correctly even after refreshing the page... but not src in img tag...
I think I have a same problem as this question: Linking to images referenced in vuex store in Vue.js
and one of the answer says
:src='student.image' (v-binding) is executed at runtime, but webpack aliases work in compile time. So you have to wrap the aliased file path in require.
{
id: 1,
name: 'Advik',
age: '19',
studying: 'Physiotherapy',
image: require('~#/assets/images/students/advik-1.png')
}
so, I would like to use require in src but icon is rendered by url not by module, so I do not know how to solve this problem. How can I make icon render after refreshing the page as well?
This is my vuex,
//---------this is default state data--------------
export const state = () => ({
user: {
email: 'default',
id: 'default',
last_name: 'default',
name: 'name',
picture: 'picture',
provider: 'default',
},
}
// -------this is to set user and token in store and local storage-------
export const mutations = {
setUser(state, authData) {
const now = new Date()
const expirationDate = now.getTime() + 36000000
localStorage.setItem('token', authData.token)
localStorage.setItem('user', JSON.stringify(authData.user))
localStorage.setItem('expirationDate', expirationDate)
state.idToken = authData.token
state.user = authData.user
},
}
//---------this is to get userdata and fire mutation to set data ---------
export const actions = {
GetUserInfo({ commit }, token) {
this.$axios
.get('/auth/user/', {
headers: { Authorization: `Bearer ${token}` },
})
.then((res) => {
console.log(res)
const user = {
email: res.data.email,
id: res.data.id,
last_name: res.data.last_name,
name: res.data.name,
picture: res.data.picture,
provider: res.data.provider,
}
return user
})
.then((user) => {
commit('setUser', { token, user })
})
},
}
and this is index.vue where I am trying to display the user info.
<template>
<div>
<div>{{ userAvatar }}</div> //this displays picture url first time and after refreshes it as well.
<img class="avatar" :src="userAvatar" alt="" /> //this displays icon with picture url first time and, after I refresh it, userAvatar renders as "picture" which was the default data of state.
</div>
</template>
export default {
computed: {
userAvatar() {
const user = this.$store.getters['authentication/getUserInfo']
console.log(user) //even after refresh it, still console the user data I got.
return user.picture
},
},
}
Thanks a lot!
The reason why I am writing here because I just got a job as a front-end developer and on the first day they threw at me a big project and I lost, very lost, hopeless.
My job would be that I am having a home page where there is a table with some information for example date, hours, the daily wind speed, daily celsius, and under the table there would be information which can be generated from a config panel.
So basically with Vue-router am having two pages, one with the home and one with the config panel, now in the config panel I am having a form where you can write your text you want to display to the home page and my problem is that I have no clue how to display that text from one router to another I tried to make a method where on submitting the form it should somehow commit that message to my Vuex state but when I am about to write it out to the home page it is now showing,
This is what I have in my modules (vuex file) :
const state = {
message: '',
};
const getters = {
message: (state) => {
return state.message;
},
};
const actions = {
setMessage: ({
commit,
state
}, newValue) => {
commit('SET_MESSAGE', newValue);
return state.message;
},
};
const mutations = {
SET_MESSAGE: (state, newValue) => {
state.message = newValue;
console.log(state.message);
},
};
export default {
state,
getters,
actions,
mutations,
};
when I am console logging the state.message the text which got submitted is there now I need to put this text to my homepage, please help me with that I know that this should be an easy one but I cannot solve it.
On home page you should add
created() {
this.$store.dispatch('SET_MESSAGE');
}
This code will call SET_MESSAGE
computed: {
...mapGetters({
message: 'message',
}),
}
After adding this part you can take message value simple call "this.message" in methods or "message" in template
i am developing a shopify theme, currently i am working on shopping cart page, i have CartForm.js file where i am importing data from cartData.js file. This is CartForm.js...
import { store } from "./../shared/cartData.js";
if (document.querySelector('.cart-form')) {
let productForm = new Vue({
el:".cart-form",
delimiters: ['${', '}'],
data(){
return{
cart:null,
}
},
created(){
this.getCart();
},
methods:{
getCart(){
store.getCart();
this.cart=store.state.cartData;
console.log("cart data: "+this.cart);
},
and this is cartData.js file
export const store = {
state: {
cartData:null
},
getCart(){
alert("store get cart called!...")
axios.get('/cart.js')
.then( response => {
this.state.cartData=response.data;
console.log("Responsed data="+this.state.cartData);
})
.catch( error => {
new Noty({
type: 'error',
layout: 'topRight',
text: 'There was an error !!'
}).show();
});
}
}
As you can see i am explicitly calling store.getCart(); in CartForm's getCart() method, and when "Responsed data" gets printed it shows that this.state.cartData filled with data, but when i am using it like this: this.cart=store.state.cartData; this.cart is null, why is null? Any help is appreciated
This happens because your API takes a while to respond, but JavaScript continues running the function in parallel. Your state is still 'null' while the call hasn't returned, thus this.cart will be set to null, unless you tell JavaScript to wait until the call is finished.
Try making the getCart() method an asynchronous function:
methods:{
async getCart(){
await store.getCart();
this.cart=store.state.cartData;
console.log("cart data: "+this.cart);
},
If cart should always be the same as the data in your store, a better way to do this might be to use a computed property for cart. This returns the store.state directly and will help you keep a single source of truth for your data.
computed: {
cart() {
return store.state.cartData
}
}