Quasar, vuexfire and this._data.$$state error
-
Hi all
I know this is not strictly a Quasar issue (probably) but hoping someone has encountered the same problem before.
Dev mode: spa
Pkg quasar: v1.11.2
Pkg @quasar/app: v1.8.6I’ve started using
vuexfire
in my Quasar app to make it easier to sync a Firebase document with vuex and all is fine when reading the document but I can’t make any changes in order to write back to Firebase. I must be missing something really simple here- I’m stuck! I have read the docs that vuexfire is only for reading because it is simple to write back using Firebase calls, but I can’t get that far due to:[Vue warn]: Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers." [vuex] do not mutate vuex store state outside mutation handlers.
Here’s my situation: I have the store set up as follows:
main store/index.js
export default function (/* { ssrContext } */) { const Store = new Vuex.Store({ modules: { auth, customerConfig }, mutations: { ...vuexfireMutations }, // enable strict mode (adds overhead!) // for dev mode only strict: process.env.DEV }) return Store }
customerConfig
is the store module that I’m binding to a Firebase document. I have an action in there:export const getCustomerConfig = firestoreAction((context, customerKey) => { console.log('[*] Binding to collection: customers document: %c' + customerKey, 'color: red;') return context.bindFirestoreRef('config', firebaseStore.collection('customers').doc(customerKey)) })
That works great. In my .vue file, I am then displaying an array from the document in a q-table, e.g. my document looks a bit like:
{ "domains": [{ "domain": "test.com", "useSpfRecord": true }, { "domain": "another.com", "useSpfRecord": false } ] }
and I use a q-table to show the domains list…
<q-table :title="data.length > 0 ? 'Domains (' + data.length + ')' : 'Domains'" :data="domains" :columns="columns" row-key="domain" :pagination.sync="pagination" no-data-label="No domains have been added yet" >
and
domains
uses a getter in computed to return just the domains array from the documentcomputed: { ...mapGetters('customerConfig', ['domains']) },
This works great, my domains are listed in the table as expected.
I then have a q-toggle in a table cell which I want to use to change the value of
useSpfRecord
in the domain object, e.g.<q-td key="useSpfRecord" :props="props"> <div> <q-toggle :color="props.row.useSpfRecord ? 'green' : 'grey'" :value="props.row.useSpfRecord" @input="updateToggle(props.key, $event)" checked-icon="done" /> </div> </q-td>
This calls an action where I plan to write back to the Firestore document with the change.
However, as soon as I try and change theuseSpfRecord
property then I get the errorexport const updateDomain = firestoreAction(({ state }, payload) => { const customerRecord = { ...state.config } // <--- Copy of the Firebase document from vuex const domains = customerRecord.domains domains.forEach((domainCfg, idx) => { if (Object.prototype.hasOwnProperty.call(domainCfg, 'domain')) { if (domainCfg.domain.toLowerCase() === payload.key.toLowerCase()) { domainCfg['useSpfRecord'] = payload.val // <--- BOOOOM!!!! } } }) })
So I don’t even get the chance to write back to Firebase with a
set
call.Any thoughts or suggestions ?
Thanks!
-
Aarrrgghhhh finally the penny dropped after I read the error eleventy billion times. It was a layer-8 problem
I was modifying the state from a Vuex action, not from a mutation handler
I moved my code into
mutations.js
and changed my @input method to call the mutation directly, rather than trying to do it through an action which it doesn’t like.updateToggle: function (key, field, val) { this.updateDomainRecord({ key, field, val }) // <--- mutation this.updateDomainConfig(key) // <--- action .then(() => { console.log('SUCCESS!') }) .catch((error) => { console.log('ERROR', error) }) }