Vuex setting variables in state from actions - vue.js

I am trying to populate the variable onSale in the state but not able to.
I am getting my data from a json file. what is wrong with my code?
A separate question is sometimes I see the word 'context' instead of 'state', what is needed for and when to use it?
Thanks for help.
state: {
products: [],
onSale: [],
},
actions: {
async fetchProducts({commit, state}) {
axios.get('/src/assets/phones.json')
.then(response => {
commit('setProducts', response.data) // setProducts(state, products) {
// alert(response.data)
})
let allM = []
await state.products.map((d) => {
for (let i = 0; i < Object.keys(d).length; i++) {
if (d["onSale"])
allM.push(d["onSale"])
}
})
//alert(allM)
//return new Promise((resolve, reject) => {
commit('setOnSale1', allM)
// alert(allM)
})
},
mutations: {
setOnSale1(state, onSale) {
state.onSale = onSale
},
},

I solve it by :
actions: {
async fetchProducts({commit, state}) {
await axios.get('/src/assets/phones.json')
.then(response => {
commit('setProducts', response.data) // setProducts(state, products) {
// alert(response.data)
})
let allM = []
state.products.map((d) => {
for (let i = 0; i < Object.keys(d).length; i++) {
// alert(d)
if (d["onSale"])
allM.push(d["onSale"])
}
})
commit('setOnSale1', allM[0])
},
.............
mutations: {
setOnSale1(state, onSale) {
state.onSale = onSale
},
}

Related

Vuex is not mutating the state

I am trying to switch authenticated from false to true, a property in the state, It's not working.
My codes from store.js
state() {
return{
authenticated : false,
user : {}
}
},
getters : {
authenticated(state){
return state.authenticated
}
},
mutations : {
set_authenticated(state, value){
return state.authenticated = value
}
},
My updated code from login.vue (script)
data() {
return {
allerrors : [],
success : false,
data: {
email : "",
password : ""
}
}
},
methods : {
login: function() {
this.$store
.dispatch("login", this.data)
.then(response => {
this.allerrors = [],
this.success = true,
this.data = {}
alert(response.data)
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
alert(allerrors)
})
},
My updated action is :
async login({ commit }, data) {
await axios.post('login', data)
.then(response => {
commit('set_authenticated',true);
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
})
}
There are a few problems here:
First, if that is the full code for your store.js file, then you are missing the call to createStore() (for Vue 3) or new Vuex.Store() (for Vue 2)
import { createStore } from 'vuex'
// Create a new store instance.
const store = createStore({
state () {
return {
count: 0
}
},
mutations: {
increment (state) {
state.count++
}
}
})
Source
The second problem is that you shouldn't be committing mutations from your Single File Components. The typical flow is:
Components dispatch actions
Actions commit mutations
Mutations update state
You're trying to commit a mutation directly from the component.
You need to add an action to your store.js
async login({ commit }, userData) {
await axios.post('login', userData)
.then(response => {
commit('set_authenticated',true);
})
.catch((error) => {
this.allerrors = error.response.data.error
this.success = false
})
}
Mutation:
mutations : {
set_authenticated(state, value){
state.authenticated = value
}
},
Then your Login.vue would change to something like:
methods: {
login: function() {
this.$store
.dispatch("login", { userData })
.then(() => )) // whatever you want to do here.
.catch(err => console.error(err));
}
}
mutations shouldn't have a return statement. it should be like this
mutations : {
set_authenticated(state, value){
state.authenticated = value
}
},

Vuejs Vuex sometimes initial state not working Error: [Vue warn]: Error in render: "TypeError: Cannot read property 'Any_Variable' of undefined"

Other pages are working fine. Only facing issue with this file. May be I am coding wrong.
Store file is included in app.js file as other pages are working I have not included it.
Here Sometimes I get undefined MDU_Number. Sometimes it work fine. I am new to vue js.
Image of error that I am receving:
This is my vue template
<div class="card-body">
<div class="form-group row">
<label class="col-sm-4 col-form-label">MDU Number</label>
<div class="col">
<input
name="MDU_Number"
:value="mduprofile.MDU_Number"
#input="updateMDUNumber"
type="text"
class="form-control"
placeholder="Enter MDU Number Ex:GJXXCHXXXX"
required
/>
</div>
</div>
</div>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
data() {
return {
};
},
created() {
this.fetchForMDU();
},
destroyed() {
this.resetState();
},
computed: {
...mapGetters("MDUSingle", [
"loading",
"country",
"area",
"product",
"mduprofile",
]),
},
methods: {
...mapActions("MDUSingle", [
"resetState",
"fetchForMDU",
"storeMDU",
"setMDUNumber",
]),
submitForm() {
this.storeMDU()
.then(() => {
this.resetState();
this.$eventHub.$emit(
"create-success",
"Created",
"MDU created successfully"
);
})
.catch((error) => {
console.log(error);
});
},
updateMDUNumber(e) {
this.setMDUNumber(e.target.value);
},
},
};
</script>
This is store file name single.js and I have included it in app.js file
MDU_Number should go for null value but it goes for undefined. So I think it is not initialized properly. There are many other variables but for simplicity purpose I have included only one.
What can be the issue?
function initialState() {
return {
mduprofile: {
MDU_Number: null,
},
country: [],
area: [],
product: [],
loading: false
};
}
const getters = {
country: state => state.country,
area: state => state.area,
product: state => state.product,
loading: state => state.loading,
mduprofile: state => state.mduprofile
}
const actions = {
fetchForMDU({ commit }) {
return new Promise((resolve, reject) => {
axios.get('/get/detail/for/mdu')
.then((response) => {
let detail = response.data;
commit('setCountryAll', detail.country);
commit('setStateAll', detail.state);
commit('setProductAll', detail.product);
}).catch(error => {
reject(error);
}).finally(() => {
resolve();
});
});
},
storeMDU({ commit, state, dispatch }) {
commit('setLoading', true);
dispatch('Alert/resetState', null, { root: true });
return new Promise((resolve, reject) => {
let params = _.cloneDeep(state.mduprofile);
axios.post('/save-mdu-profile', params)
.then((response) => {
resolve();
})
.catch(error => {
commit('setLoading', false);
let message = error.response.data.message || error.message;
let errors = error.response.data.errors;
dispatch('Alert/setAlert',
{ message: message, errors: errors, color: danger },
{ root: true });
reject(error);
}).finally(() => {
commit('setLoading', false);
});
});
},
fetchData({ commit }, value) {
axios.get('/mdu/profile/' + value)
.then((response) => {
commit('setAll', response.data.mdu);
}).catch(error => {
}).finally(() => {
});
},
updateMDU({ commit, state, dispatch }) {
commit('setLoading', true);
dispatch('Alert/setAlert', null, { root: true });
return new Promise((resolve, reject) => {
let params = _.cloneDeep(state.mduprofile);
axios.put('/update-mdu-profile/' + params.MDU_Id, params)
.then((response) => {
resolve();
}).catch(error => {
let message = error.response.data.message || error.message;
let errors = error.response.data.errors;
dispatch('Alert/setAlert',
{ message: message, errors: errors, color: danger },
{ root: true });
commit('setLoading', false);
reject(error);
}).finally(() => {
commit('setLoading', false);
});
});
},
resetState({ commit }) {
commit('resetState');
},
setMDUNumber({ commit }, value) {
commit('setMDUNumber', value);
}
}
const mutations = {
resetState(state) {
state = Object.assign(state, initialState());
},
setLoading(state, loading) {
state.loading = loading;
},
setCountryAll(state, items) {
state.country = items
},
setStateAll(state, items) {
state.area = items;
},
setProductAll(state, items) {
state.product = items;
},
setAll(state, items) {
state.mduprofile = items;
},
setMDUNumber(state, value) {
state.mduprofile.MDU_Number = value;
},
setCountry(state, value) {
state.mduprofile.Country = value;
},
setState(state, value) {
state.mduprofile.State = value;
},
setProduct(state, value) {
state.mduprofile.Product = value;
}
}
export default {
namespaced: true,
state: initialState,
getters,
actions,
mutations
}
Try checking somewhere where you change this values, if you don't catch error properly you may encounter empty states.

Vue ajax request isn't updating data

I'm new to Vue but from my research this should be working. the console keeps showing users as null but when i look at the response of the request it has the users. I thought the => was supposed to update the vue instance.
...
data () {
return {
users: null,
}
},
...
methods: {
getUsers () {
this.$axios.get('/api/users')
.then(r => {
this.users = r.data
})
console.log(this.users)
},
},
...
created () {
this.getUsers()
this.users.forEach(function (u) {
...
})
}
If you want to loop through the collection of users, you have to first wait until they are actually available - you can use then callback for it:
export default {
data () {
return {
users: [],
}
},
methods: {
getUsers () {
return this.$axios.get('/api/users')
.then(r => {
this.users = r.data
})
.catch(error => console.log(error));
},
},
created () {
this.getUsers().then(() => {
this.users.forEach(function (u) {
...
})
})
}
}
Rather than converting returned collection from within vue component it would be better to return it formatted with the response - using plain php you could achieve it with array_map - here I'm using an array of User models as an example:
$users = array_map(function (User $user) {
return [
'value' => $user->id,
'name' => $user->name,
];
}, $users);
The above will return something like:
[
[
'value' => 1,
'name' => 'Jon Doe',
],
[
'value' => 2,
'name' => 'Jane Doe',
],
]
You can move your users processing to a watcher:
...
data () {
return {
users:[],
}
},
watch: {
users (users) {
if( ! this.users.length )
return;
this.users.forEach(function (u) {
...
})
},
},
...
methods: {
getUsers () {
this.$axios.get('/api/users')
.then(r => {
this.users = r.data
})
console.log(this.users)
},
},
...
created () {
this.getUsers()
}
Or if you prefer a one time processing, make it a method and call that method in the axios then():
...
methods: {
getUsers () {
this.$axios.get('/api/users')
.then(r => {
this.users = r.data
this.processUsers();
})
console.log(this.users)
},
processUsers() {
// do something with this.users
},
},

Vuex Store does not update [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
I've been refactoring my Vue SPA and one of the changes I was wanting to make has been the removal of manually importing "Store" in every component that needs it and instead uses the "this.$store.dispatch('module/update', data)", but it doesn't update the store like "Store.dispatch('module/update', data)" used to in the past.
methods: {
update() {
let office = {
id: this.office.id,
name: this.name,
description: this.description,
abbreviation: this.abbreviation
};
this.$http.post('/api/office/update', office).then(function(result) {
Store.dispatch('offices/update', result.data);
this.$router.push({ path: '/settings/offices' });
}).catch((error) => {
this.$router.push({ path: '/settings/offices' });
});
}
}
export const Offices = {
namespaced: true,
state: {
all: []
},
mutations: {
ADD_OFFICE: (state, offices) => {
offices.forEach(office => {
state.all.push(office);
});
},
DELETE_OFFICE: (state, id) => {
state.all.splice(state.all.map((office) => { return office.id }).indexOf(id), 1);
},
UPDATE_OFFICE: (state, data) => {
Object.assign(state.all.find((office) => office.id === data.id), data);
}
},
actions: {
get(context) {
Axios.get('/api/office/all').then((response) => {
context.commit('ADD_OFFICE', response.data);
});
},
create(context, office) {
context.commit('ADD_OFFICE', office);
},
update(context, data) {
context.commit('UPDATE_OFFICE', data);
},
delete(context, id) {
context.commit('DELETE_OFFICE', id);
}
}
}
I expected it to update the store as importing it manually does.
Mutations should be immutable to make data reactive
mutations: {
ADD_OFFICE: (state, offices) => {
state.all = state.all.concat(offices)
},
DELETE_OFFICE: (state, id) => {
state.all = state.all.filter(office => office.id != id)
},
UPDATE_OFFICE: (state, data) => {
const officeIndex = state.all.findIndex(office => office.id === data.id)
const newObj = Object.assign(state.all[officeIndex], data)
state.all = [
...state.all.slice(0, officeIndex),
newObj,
...state.all.slice(officeIndex + 1)
]
}
},

Cannot assign axios response value to a variable - vue.js

I created an array lists that contains a few strings.
Now I want to loop through lists (i.e., in getSubs()) and make an Axios request. This request should contain one string from lists each time.
My code:
computed: {
subscribers: {
get() {
return this.$store.state.subscribers;
},
set(value) {
this.$store.commit('updateSubscribers', value);
},
},
},
methods: {
getLodzkie() {
axios
.get(`correct_domain/lodzkietargi/get`)
.then((response) => {
this.subscribers = [];
this.subscribers.push.apply(this.subscribers, response.data)
})
.catch(function(error) {
console.log(error);
})
},
getSubs() {
function getSub(value) {
axios
.get(`correct_domain/${value}/get`)
.then((response) => {
this.subscribers.push.apply(this.subscribers, response.data)
})
.catch(function(error) {
console.log(error);
});
console.log(value);
}
this.lists.forEach(function(entry) {
getSub.call(null, entry);
});
},
getLodzkie() works beautifully
Thank You a lot #ourmandave. That helped me perfectly.
Rewrote function below:
getSubs() {
let listsReqs = this.lists.map(list => {
return axios.get(`correct_domain/${list}/get`);
});
axios.all(listsReqs)
.then(axios.spread((...responses) => {
responses.forEach(res => this.subscribers.push.apply(this.subscribers, res.data));
})
)},