Uncaught Error: Module parse failed: Shorthand property assignments are valid only in destructuring patterns - vuex

I get this error:
Uncaught Error: Module parse failed: Shorthand property assignments are valid only in destructuring patterns (74:14)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| dispatch('ADD_CHILDREN_TO_NODE', {
> doc = doc,
| })
| .finally(() => {
at eval (document-flow.module.js:1)
at Object../src/main/code/customers-self-data/vuex/modules/document-flow.module.js (_bundle.js?97212a2ac8be2d4b571f:8449)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (store.js:8)
at Module../src/main/code/customers-self-data/vuex/store.js (_bundle.js?97212a2ac8be2d4b571f:8473)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (index.js:3)
at Module../src/main/code/customers-self-data/index.js (_bundle.js?97212a2ac8be2d4b571f:8378)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (index.js:1)
This is my module:
import * as a from "../types/actions.types";
import * as g from "../types/getters.types";
import * as m from "../types/mutations.types";
import {
some imports
} from "#pn-js/core";
const documentFlow = {
namespaced: true,
state: {
documentFlowTree: null,
documentId: null,
childrens: null,
},
getters: {
[g.GET_DOCUMENT_FLOW_TREE](state) {
return state.documentFlowTree;
},
[g.GET_DOCUMENT_ID](state) {
return state.documentId;
},
[g.GET_CHILDRENS](state) {
return state.childrens;
},
},
mutations: {
[m.SET_DOCUMENT_FLOW_TREE](state, payload) {
state.documentFlowTree = payload;
},
[m.SET_DOCUMENT_ID](state, payload) {
state.documentId = payload.id;
},
[m.SET_CHILDRENS](state, payload) {
state.childrens = payload.childrens;
},
},
actions: {
[a.LOAD_DOCUMENT_FLOW_TREE]({ dispatch,commit, state }) {
var _documentTypeNamesMap = {
ORDER: order,
DELIVERY: delivery,
INVOICE: invoice,
};
let params = new ParamsBuilder(url)
.param(ParamsBuilder.UrlReplacements.ID, state.documentId)
.build();
let res = [];
return Http.get({ params }).then((response) => {
//Compongo il nodo root
let firstNodeText =
_documentTypeNamesMap.ORDER + ":\t" + state.documentId;
let doc = [];
if (response.result) {
Object.keys(response.result).forEach((key) => {
doc.push(response.result[key].sequentDocuments.filter((d) => {
return d.docType.category === "DELIVERY";
}));
});
}
dispatch('ADD_CHILDREN_TO_NODE', { ====> This generates the error
doc = doc,
})
.finally(() => {
if (response.result) {
res.push({
text: firstNodeText,
state: { expanded: true },
children: state.childrens,
});
} else {
res = [
{
text: firstNodeText,
state: { expanded: true },
children: [{ text: noDataFound }],
},
];
}
commit(m.SET_DOCUMENT_FLOW_TREE, res);
});
});
},
[a.UPDATE_DOCUMENT_ID]({ commit }, payload) {
commit(m.SET_DOCUMENT_ID, payload);
},
[a.ADD_CHILDREN_TO_NODE]({commit},payload) {
let doc = payload.doc;
let childrens = [];
let matRegNodeText = "";
let i = 0;
Object.keys(doc).forEach((key) =>{
let docId = doc[key][0].docNum;
let deliveryParams = new ParamsBuilder(url)
.param(ParamsBuilder.UrlReplacements.NUM, docId)
.build();
Http.get({
params: deliveryParams,
}).then((deliveryResponse) => {
if (deliveryResponse.result) {
matRegNodeText =
(doc[key][0].docType.category === "DELIVERY" ? goodsIssue : null) +
"\t\t\t" +
deliveryResponse.result.goodsReceiptNum +
"\t\t\t" +
deliveryResponse.result.actualMovDate;
}
let child = {
text: Strings.fsa.cdp.df.position + "\t" + response.result[i].docPos.posNum,
state: { expanded: true },
children: [{ text: matRegNodeText }],
};
childrens.push(child);
i++;
});
});
commit(m.SET_CHILDRENS,childrens);
}
},
};
export default documentFlow;
My question: is it possible to call an action from an action on the same module?
My problem is that before I didn't use the action to build the node (in the action loop my object doc to retrieve the data) but before being able to push the array childrens into property children of the object res, it was called asynchronous the commit, I thought about putting that piece of code inside a promise and then building the tree node but the result was the same.

Related

Vue store and computed doesnot reactive even with vue set

I have following computed property in my Vue component:
computed: {
contragent_id: {
get() {
return appData.getters["basket/contragent_id"];
},
set(value) {
return value;
},
},
settings: {
get() {
return appData.getters["basket/delivery_settings"];
},
set(value) {
return value;
},
},
presets: {
get() {
return appData.getters["basket/delivery_presets"];
},
set(value) {
return value;
},
},
},
And i have the Vuex store module :
const moduleBasket = {
namespaced: true,
state: () => ({
presets: {
contragents: [],
partners: {},
delivery: {
types: {},
methods: {},
tc_methods: {},
tc_list: {},
addresses: [],
},
},
summary: {
delivery: {
delivery_type: "",
delivery_method: "",
delivery_tc: "",
delivery_tc_method: "",
delivery_tc_city: "",
delivery_address_id: "",
},
payment: {
method: "",
methodText: "",
},
address: {},
comment: "",
partner_id: "",
contragent_id: "",
price: {
total: "",
nds: "",
delivery: "",
discount: "",
},
fillial: {
address: "",
},
},
}),
mutations: {
changeFillial(state, fillial) {
Vue.set(state.summary, "fillial", fillial);
},
changePartnerId(state, partner_id) {
Vue.set(state.summary, "partner_id", partner_id);
},
changeContragentId(state, contragent_id) {
Vue.set(state.summary, "contragent_id", contragent_id);
// state.summary.contragent_id = contragent_id;
},
changeContragents(state, contragnets) {
Vue.set(state.presets, "contragents", contragnets);
// state.presets.contragents = contragnets;
},
changePartners(state, partners) {
Vue.set(state.presets, "partners", partners);
// state.presets.partners = partners;
},
changeDeliveryPresets(state, presets) {
// console.log('changeDeliveryPresets');
Vue.set(state.presets, "delivery", presets);
// state.presets.delivery = presets;
},
changeDeliveryPresets__types(state, types) {
// console.log('changeDeliveryPresets__types');
Vue.set(state.presets.delivery, "types", types);
// state.presets.delivery.types = types;
},
changeDeliveryPresets__methods(state, methods) {
Vue.set(state.presets.delivery, "methods", methods);
// state.presets.delivery.methods = methods;
},
changeDeliveryPresets__tc_methods(state, tc_methods) {
Vue.set(state.presets.delivery, "tc_methods", tc_methods);
// state.presets.delivery.tc_methods = tc_methods;
},
changeDeliveryPresets__tc_list(state, tc_list) {
Vue.set(state.presets.delivery, "tc_list", tc_list);
// state.presets.delivery.tc_list = tc_list;
},
changeDeliveryPresets__addresses(state, addresses) {
Vue.set(state.presets.delivery, "addresses", addresses);
// state.presets.delivery.addresses = addresses;
},
changeDelivery(state, delivery) {
for (let key in delivery) {
Vue.set(state.summary.delivery, key, delivery[key]);
// state.summary.delivery[key]=delivery[key];
}
},
changeDelivery__tc_city(state, tc_city) {
Vue.set(state.summary.delivery, "delivery_tc_city", tc_city);
// state.summary.delivery.delivery_tc_city = tc_city;
},
changeDelivery__tc(state, tc) {
Vue.set(state.summary.delivery, "delivery_tc", tc);
// state.summary.delivery.delivery_tc = tc;
},
changeDelivery__method(state, method) {
Vue.set(state.summary.delivery, "delivery_method", method);
// state.summary.delivery.delivery_method = method;
},
changeDelivery__delivery_type(state, delivery_type) {
console.log("setting delivery");
Vue.set(state.summary.delivery, "delivery_type", delivery_type);
// state.summary.delivery.delivery_type = delivery_type;
},
changeDelivery__address_id(state, address_id) {
Vue.set(state.summary.delivery, "delivery_address_id", address_id);
// state.summary.delivery.delivery_address_id = address_id;
},
changeDelivery__address(state) {
state.summary.address = {};
if (state && state.summary.delivery) {
if (state.presets && state.presets.addresses && state.summary.delivery && ((state.summary.delivery.delivery_method == "tc" && state.summary.delivery.delivery_tc_method == "door") || state.summary.delivery.delivery_method == "courier")) {
if (state.presets && state.presets.addresses && state.summary.delivery && state.summary.delivery && state.summary.delivery.delivery_address_id) {
Vue.set(
state.summary,
"address",
state.presets.addresses.find((address) => address.id == state.summary.delivery.delivery_address_id)
);
}
} else {
if (state.summary.delivery && state.summary.delivery.delivery_tc_city) {
Vue.set(state.summary, "address", {
address: state.summary.delivery.delivery_tc_city,
});
}
}
}
},
},
actions: {
//COMMON DATA
changeFillial: ({ commit }, { fillial }) => commit("changeFillial", fillial),
changePartnerId: ({ commit }, { partner_id }) => {
console.log("partner id commit");
commit("changePartnerId", partner_id);
},
changeContragentId: ({ commit }, { contragent_id }) => {
commit("changeContragentId", contragent_id);
},
changeContragents: ({ commit }, { contragents }) => {
commit("changeContragents", contragents);
},
changePartners: ({ commit }, { partners }) => {
commit("changePartners", partners);
},
//PRESETS
changeDeliveryPresets: ({ commit }, { presets }) => {
commit("changeDeliveryPresets", presets);
commit("changeDelivery__address");
},
changeDeliveryPresets__types: ({ commit }, { types }) => {
commit("changeDeliveryPresets__types", types);
},
changeDeliveryPresets__methods: ({ commit }, { methods }) => {
commit("changeDeliveryPresets__methods", methods);
},
changeDeliveryPresets__tc_methods: ({ commit }, { tc_methods }) => {
commit("changeDeliveryPresets__tc_methods", tc_methods);
},
changeDeliveryPresets__tc_list: ({ commit }, { tc_list }) => {
commit("changeDeliveryPresets__tc_list", tc_list);
},
changeDeliveryPresets__addresses: ({ commit }, { addresses }) => {
commit("changeDeliveryPresets__addresses", addresses);
},
//SUMMARY
changeDelivery: ({ commit }, { delivery }) => {
commit("changeDelivery", delivery);
commit("changeDelivery__address");
},
changeDelivery__tc_city: ({ commit }, { tc_city }) => {
commit("changeDelivery__tc_city", tc_city);
},
changeDelivery__tc: ({ commit }, { tc }) => {
commit("changeDelivery__tc", tc);
},
changeDelivery__tc_method: ({ commit }, { tc_method }) => {
commit("changeDelivery__tc_method", tc_method);
},
changeDelivery__delivery_type: ({ commit }, { delivery_type }) => {
commit("changeDelivery__delivery_type", delivery_type);
},
changeDelivery__delivery_method: ({ commit }, { delivery_method }) => {
commit("changeDelivery__delivery_method", delivery_method);
},
changeDelivery__address_id: ({ commit }, { address_id }) => {
commit("changeDelivery__address_id", address_id);
},
},
getters: {
summary: (state) => {
return state.summary;
},
presets: (state) => {
return state.presets;
},
delivery_tc_title: (state) => {
return state.presets && state.presets.delivery && state.presets.delivery.tc_list && state.summary && state.summary.delivery && state.summary.delivery.delivery_tc ? state.presets.delivery.tc_list[state.summary.delivery.delivery_tc] : "";
},
delivery_tc_method_title: (state) => {
return state.presets && state.presets.delivery && state.presets.delivery.tc_methods && state.summary && state.summary.delivery && state.summary.delivery.delivery_tc_method ? state.presets.delivery.tc_methods[state.summary.delivery.delivery_tc_method] : "";
},
contragent_id: (state) => {
return state.summary && state.summary.contragent_id ? state.summary.contragent_id : "";
},
contragent: (state) => {
return state.presets && state.presets.contragents && state.summary && state.summary.contragent_id ? state.presets.contragents[state.summary.contragent_id] : "";
},
partner_id: (state) => {
return state.summary && state.summary.partner_id ? state.summary.partner_id : "";
},
partner: (state) => {
return state.presets && state.presets.partners && state.presets.partners.length && state.summary && state.summary.partner_id ? state.presets.partners.find((partner) => partner.id == state.summary.partner_id) : "";
},
partners: (state) => {
return state.presets && state.presets.partners ? state.presets.partners : "";
},
contragents: (state) => {
return state.presets && state.presets.contragents ? state.presets.contragents : "";
},
delivery: (state) => {
return state.summary && state.summary.delivery ? state.summary.delivery : "";
},
delivery_presets: (state) => {
return state.presets && state.presets.delivery ? state.presets.delivery : "";
},
delivery_settings: (state, getters) => {
return {
delivery: getters["delivery"],
address: getters["address"],
fillial: getters["fillial"],
};
},
fillial: (state) => {
return state.summary && state.summary.fillial ? state.summary.fillial : "";
},
},
};
In the template the
{{ presets }}
{{ settings}}
returns { "types": {}, "methods": {}, "tc_methods": {}, "tc_list": {}, "addresses": [] } { "delivery": { "delivery_type": "", "delivery_method": "", "delivery_tc": "", "delivery_tc_method": "", "delivery_tc_city": "", "delivery_address_id": "" }, "fillial": { "address": "" } }
like initial in store
When i use getter in console appData.getters["basket/delivery_settings"]
it return the valid real time object
Also settimeouts like that
mounted() {
setTimeout(() => {
console.log(this.presets);
console.log(this.settings);
}, 10000);
},
returns the valid object too.
Whats is my mistake?Can someone help me?
The setters of computed are returning. Instead, they should be committing.
Think of getter + setter computed as a collection of read (getter) and write (setter) functions.
Let's take one of the computed apart:
contragent_id: {
get() {
return appData.getters["basket/contragent_id"];
},
set(value) {
return value;
},
}
Let's consider a read operation:
const myValue = this.contragent_id
if the code would be able to describe what it does, it would be saying something like:
I read the value from appData.getters["basket/contragent_id"] (which returns the value of appData.state.summary.contragent_id) and store it in a constant named myValue.
Great! That's exactly what it should be doing. Now let's consider a write operation (a setter):
console.log(this.contragent_id) // Expect: ''; Receive: ''
this.contragent_id = '42'
console.log(this.contragent_id) // Expect: '42'. Receive: ''
the current code (return value) would be described by:
Here's "42"! I'm giving it back to you, I'm not doing anything with it.
It should be described by:
I write '42' into state.summary.contragent_id, by committing this value to the 'basket/changeContragentId' mutation.
, which would look like:
set(value) {
appData.commit('basket/changeContragentId', value)
}
Once the mutation is performed, because of it, the getter immediately updates and starts returning the current value of state.summary.contragent_id, via getters['basket/contragent_id'], which is now 42 (or whatever we assigned).
In other words, with the committing setter, the above code will produce:
console.log(this.contragent_id) // Expect: ''; Receive: ''
this.contragent_id = '42'
console.log(this.contragent_id) // Expect: '42'; Receive: '42'
So the local computed contragent_id can now be read from and written to. In fact, we'd be interacting with state.summary.contragent_id, via getters and mutations.
On a separate note, we shouldn't be using Vue.set() everywhere in our mutations.
We probably want to write the above mutation as:
changeContragentId(state, contragent_id) {
state.summary = { ...state.summary, contragent_id };
}
Why?
{ ...state.summary, contragent_id }
is shorthand for:
{ ...state.summary, contragent_id: contragent_id }
, which creates a fresh object from state.summary containing everything that state.summary contained, plus the passed argument contragent_id's value, assigned to the contragent_id property of this new object, regardless of whether or not the old state.summary had such a property or any value in it. By assignment, state.summary's value is replaced with this new object. This replacement is what notifies the getters which, in turn, update all components using them (or reading directly from state).
This is the key: replacing the root prop of the state.
If we would have used
state.summary.contragent_id = value
state.summary object wouldn't have been replaced, and the change would not be visible in <template>.
In some cases (when something else is changed at the same time), we might see changes made to deep properties, giving a wrong impression about how Vue works.
I see a lot of repetition in both mutations and getters. It's unnecessary.
For example, we could replace all state.summary related mutations with a single one:
mutations: {
updateSummary(state, update) {
state.summary = { ...state.summary, ...update }
}
}
and now we could replace all state.summary related setters in components computed with calls to this mutation. Example:
computed: {
contragent_id: {
get() { return appData.getters['basket/contragent_id'] },
set(contragent_id) {
appData.commit('basket/updateSummary', { contragent_id })
}
},
partner_id: {
get() { return appData.getters['basket/partner_id'] },
set(partner_id) {
appData.commit('basket/updateSummary', { partner_id })
}
},
delivery: {
get() { return appData.getters['basket/delivery'] },
set(delivery) {
appData.commit('basket/updateSummary', { delivery })
}
},
fillial: (state) => {
get() { return appData.getters['basket/fillial'] },
set(fillial) {
appData.commit('basket/updateSummary', { fillial })
}
}
}
, which could be written as:
computed: {
...Object.assign(
{},
...["contragent_id", "partner_id", "delivery", "fillial"].map((key) => ({
[key]: {
get() {
return appData.getters[`basket/${key}`];
},
set(value) {
appData.commit("basket/updateSummary", { [key]: value });
},
},
}))
),
};
This looks complicated, doesn't it?
It's useful, we could re-use it in any component where we want to get or set state.summary props and all we'd have to do is specify a different array of keys, depending on what we want to expose.
So let's write a function, taking in the array of keys and place it in some storeHelpers.js file:
import { appData } from './path/to/appData'
export const mapSummary = (keys) =>
Object.assign(
{},
...keys.map((key) => ({
[key]: {
get() {
return appData.getters[`basket/${key}`];
},
set(value) {
appData.commit("basket/updateSummary", { [key]: value });
},
},
}))
);
Now we can
import { mapSummary } from './path/to/storeHelpers'
export default {
computed: {
...mapSummary(["contragent_id", "partner_id", "delivery", "fillial"])
}
}
Similarly, you could do this for any object you want to update inside the state, so you wouldn't have to write a mutation for each of its properties. In your case, you probably want to have updatePresets and updatePresetsDelivery mutation functions and mapPresets & mapPresetsDelivery helpers, because both state.presets and state.presets.delivery are objects.
If your state has a lot of objects inside other objects, rather than writing one mutation and one mapper function for each individual object (which is still an improvement over writing a mutation for each individual object property), you might consider a single updateBasket mutation and one mapBasket helper which would also take the object's path as a parameter. Now, that mutation, having a dynamic path, would be a good use case for Vue.set().
Keep in mind nesting objects inside other objects inside a state is generally a sign of poor architecture. In your specific case, I'd probably go for three separate stores: one called basketSummary, one called basketPresets and one called basketPresetsDelivery (or basketDelivery).
Alternatively, you could go for nested stores, which would be be basket/summary, basket/presets and basket/presets/delivery, since you're using namespacing. Namespacing was actually developed to address cases like yours.
This subject is debatable (a lot of developers have strong opinions about store architecture) but, from my experience, having many smaller stores, each controlling a flat structure (a level: the properties of only one object) is generally preferable to having one big store, with lots of getters, actions and mutations, each having multiple levels of object spreading (or having to use Vue.set()).
It simplifies testing and debugging.
Ultimately, it allows more granular/precise control over complex data structures, considerably reducing the time spent developing (and debugging).
Readability in getters could also be improved:
getters: {
contragent_id: (state) => {
return state.summary && state.summary.contragent_id
? state.summary.contragent_id
: "";
}
}
could be written as:
getters: {
contragent_id: (state) => state.summary?.contragent_id || ""
}

VueJS $set not making new property in array of objects reactive

In my VueJS 2 component below, I can add the imgdata property to each question in the area.questions array. It works - I can see from the console.log that there are questions where imgdata has a value. But despite using $set it still isn't reactive, and the imgdata isn't there in the view! How can I make this reactive?
var componentOptions = {
props: ['area'],
data: function() {
return {
qIndex: 0,
};
},
mounted: function() {
var that = this;
that.init();
},
methods: {
init: function() {
var that = this;
if (that.area.questions.length > 0) {
that.area.questions.forEach(function(q) {
Util.HTTP('GET', '/api/v1/photos/' + q.id + '/qimage').then(function(response) {
var thisIndex = (that.area.questions.findIndex(entry => entry.id === q.id));
var thisQuestion = (that.area.questions.find(entry => entry.id === q.id));
thisQuestion.imgdata = response.data;
that.$set(that.area.questions, thisIndex, thisQuestion);
})
});
}
console.log("area.questions", that.area.questions);
},
Since area is a prop, you should not be attempting to make changes to it within this component.
The general idea is to emit an event for the parent component to listen to in order to update the data passed in.
For example
export default {
name: "ImageLoader",
props: {
area: Object
},
data: () => ({ qIndex: 0 }), // are you actually using this?
mounted () {
this.init()
},
methods: {
async init () {
const questions = await Promise.all(this.area.questions.map(async q => {
const res = await Util.HTTP("GET", `/api/v1/photos/${encodeURIComponent(q.id)}/qimage`)
return {
...q,
imgdata: res.data
}
}))
this.$emit("loaded", questions)
}
}
}
And in the parent
<image-loader :area="area" #loaded="updateAreaQuestions"/>
export default {
data: () => ({
area: {
questions: [/* questions go here */]
}
}),
methods: {
updateAreaQuestions(questions) {
this.area.questions = questions
}
}
}
Here that variable has a value of this but it's bound under the scope of function. So, you can create reactive property in data as below :
data: function() {
return {
qIndex: 0,
questions: []
};
}
Props can't be reactive so use :
that.$set(this.questions, thisIndex, thisQuestion);
And assign your API output to directly questions using this.questions.

Cannot pass multiple arguments in vuex actions

I'm trying to call vuex action in vue component with multiple parameters. But in action method cannot access these passed arguments.
I have already tried passing value in payload as object which is mostly suggested here. but still it is not working.
Please look for
this.getMessageFromServer(payload);
MessageBox.vue
import Vue from 'vue';
import { mapGetters, mapActions } from 'vuex';
import MessageView from './MessageView.vue';
export default Vue.component('message-box',{
components:{
MessageView
},
data() {
return {
messageList :[],
}
},
created() {
this.fetchTimeMessage();
console.log("reaching inside ");
},
computed:{
...mapGetters(['getMessage','getActiveMessageData']),
...mapActions(['getMessageFromServer']),
},
methods: {
fetchTimeMessage:function(){
console.log("fetchTimeMessage : ");
var messageUser = this.getMessage.findIndex((e) => e.muid == this.getActiveMessageData.id);
console.log("fetchTimeMessage : " , {messageUser});
if (messageUser == -1) {
let user_id = this.getActiveMessageData.id;
let user_type = this.getActiveMessageData.type;
console.log("inside fetch Message : " + user_id);
console.log("inside fetch Message : " + user_type);
const payload = {
'uType': user_type,
'uid' : user_id,
'limit': 50
};
this.getMessageFromServer(payload);
}
},
},
});
Vuex modules message.js
const state = {
messages:[],
activeMessage : {}
};
const getters = {
getActiveUserId: (state) => {
let activeUserId = "";
if (!utils.isEmpty(state.activeMessage)) {
activeUserId = state.activeMessage.id;
}
return activeUserId;
},
getActiveMessage:(state) => { return !utils.isEmpty(state.activeMessage);},
getActiveMessageData : (state) => {return state.activeMessage } ,
getMessage: (state) => {return state.messages},
};
const actions = {
getMessageFromServer({ commit, state },{utype,uid,limit}){
console.log("mesage callback asdas : " + uid);
let messageRequest = CCManager.messageRequestBuilder(utype, uid, limit);
messageRequest.fetchPrevious().then(messages => {
//console.log("mesage callback : " + JSON.stringify(messages));
// handle list of messages received
let payload = {
'messsages':messages,
'id': uid
};
console.log("inside action_view : " + JSON.stringify(payload));
//commit('updateMessageList',payload);
})
},
setActiveMessages:function({commit},data){
commit('updateActiveMessage',data);
},
};
const mutations = {
updateMessageList(state,{messages,id}){
console.log("action details" + id);
//uid is not present
var tempObj = {
'muid' : id,
'message' : messages
}
state.messages.push(tempObj);
}
},
updateActiveMessage(state,action){
state.activeMessage = {
type: action.type,
id: action.uid
};
}
};
export default {
state,
getters,
actions,
mutations
};
Change the way you call the action in your component:
this.$store.dispatch('getMessageFromServer', payload);
And pass the payload as a single object in your action function:
getMessageFromServer({ commit, state }, payload)
And you can then access the payload properties in the action like this:
getMessageFromServer({ commit, state }, payload) {
var uid = payload.uid;
var uType = payload.uType;
var limit = payload.limit;
}

Redux testing issue with Chai

I'm learning react redux, I'm currently implementing some reducers using TDD. I'm working with a sample application, it's just a notepad for adding/removing/opening/closing notes.
I'm making some tests for adding a new note, but the second "it" is failing, the error that throws me is the following:
1) AddNote reducer should return two notes:
AssertionError: expected { Object (id-123, id-456) } to equal { Object (byId, ids, ...) }
describe('AddNote reducer' , () => {
it('should return a new note', () => {
const state = getMockState.withNoNotes();
const actualNextState = reducers.byId(
state.byId, actions.addNote(
'Hello World', 'id-123', 1));
const expectedNextState = {
'id-123': {
id: 'id-123',
content: 'Hello World',
timestamp: 1
}
};
expect(actualNextState).to.deep.equal(expectedNextState);
});
it('should return two notes', () => {
const state = getMockState.withOneNote();
const actualNextState = reducers.byId(state.byId, actions.addNote('Bye bye world!', 'id-456', 2));
const expectedNextState = {
...state,
'id-456': {
id: 'id-456',
content: 'Bye bye world!',
timestamp: 2
}
};
expect(actualNextState).to.deep.equal(expectedNextState);
});
});
I'm using also a helper, here it is
export const getMockState = {
withNoNotes: () => ({
byId: {},
ids: [],
openNoteId: null,
}),
withOneNote: () => ({
byId: {
'id-123': {
id: 'id-123',
content: 'Hello world',
timestamp: 1,
},
},
ids: ['id-123'],
openNoteId: 'id-123',
}),
};
The idea is if I add a note in the first case it would return a new state with just that note, but in the second case, it should return a state with the previous note, plus the new one.
I'm using Chai expect library with mocha.
If it helps here's the output of the state (it's a console log), which I think is ok,
{ 'id-123': { id: 'id-123', content: 'Hello World', timestamp: 1 } }
√ should return a new note
{ 'id-123': { id: 'id-123', content: 'Hello world', timestamp: 1 },
'id-456': { id: 'id-456', content: 'Bye bye world!', timestamp: 2 } }
1) should return two notes
Here's is my reducer
import { merge } from 'ramda';
export const byId = (state={}, {type, payload}) => {
switch(type) {
case 'app/addNote':
console.log(merge(state, { [payload.id]: payload})) ;
return merge(state, { [payload.id]: payload});
default:
return state;
}
};
Any ideas? thanks in advance!
Your expectedState is not correct. You are comparing the "next state" of byId slice, but your expectedNextState extends the whole state. It should actually be:
const expectedNextState = {
...state.byId,
'id-456': {
id: 'id-456',
content: 'Bye bye world!',
timestamp: 2
}
};

Realm "observer.next create #[native code]" exception

I am trying to fetch data with apollo and then write it to realm. I have created a js file that I know works, because it has worked before. But, when I try to write to a particular model I get an error message. More details as follows:
Code (Not entire code) LocationQuery.js:
const realm = new Realm({ schema: [testBuilding1], schemaVersion: 1 });
let buildingTypeArray = [];
const temp = [];
class LocationQuery extends Component {
static get propTypes() {
return {
data: React.PropTypes.shape({
loading: React.PropTypes.bool,
error: React.PropTypes.object,
sites: React.PropTypes.array,
}).isRequired,
};
}
render() {
if (this.props.data.loading) {
return (null);
}
if (this.props.data.error) {
return (<Text>An unexpected error occurred</Text>);
}
if (this.props.data.sites) {
this.props.data.sites.map((value) => {
buildingTypeArray.push(value.locations);
});
buildingTypeArray.forEach((locationValues) => {
realm.write(() => {
realm.create('testBuilding1', {
building: '273',
});
});
});
}
return null;
}
}
const locationQueryCall = gql`
query locationQueryCall($id: String!){
sites(id: $id){
locations {
building
type
}
}
}`;
const ViewWithData = graphql(locationQueryCall, {
options: props => ({
variables: {
id: 'SCH1',
},
}),
})(LocationQuery);
export default connect(mapStateToProp)(ViewWithData);
The error I get is a big red screen that read:
console.error: "Error in observe.next.... blah blah blah"
The Model I am using:
export const testBuilding1 = {
name: 'testBuilding1',
properties: {
building: 'string',
},
};
The weird thing is that the code works when I use this model:
export const locationScene = {
name: 'locationScene',
properties: {
building: 'string',
},
};
I am calling LocationQuery.js in another piece of code passing it through at render.
Thank you in advance for the help!