I just started using vuex with vue. I do (roughly) understand the docs. I have a specific issue for which I am not sure whether I should use vuex and if so how to go about.
I have an app in which mapbox map(s) are omnipresent in various layouts and components etc. As I will be making several vue single file components but are working with one same instance of a mapbox map I think it makes sense to have the mapbox map initiated and managed in the vuex store. So e.g. when I change the map layout or something else, it will be reflected in all components.
When I continue in this direction I am puzzled by a couple of things:
I tried following:
Made a mapboxmap module, with
mapboxmap.js
import simple from '../../components/simplestyle'
let mapboxgl = require('mapbox-gl/dist/mapbox-gl.js')
// initial state
const state = {
myMap: {},
mapLoaded: false
}
const mutations = {
loadMap (state, myMap) {
state.myMap = myMap
state.mapLoaded = true
}
}
const actions = {
loadMap (context) {
'use strict'
mapboxgl.accessToken = 'mysecretmapboxcode'
let myMap = new mapboxgl.Map({
container: 'map',
style: simple,
hash: true,
center: [-74.0073, 40.7124],
zoom: 16
})
context.commit('loadMap', myMap)
}
}
export default {
state,
mutations,
actions
}
And as component:
Maplayout.vue
<template>
<div>
<div id='map' class='map'>
</div>
</div>
</template>
<script type='text/babel'>
export default {
mounted () {
this.computed.myMapForView.set().then(() => this.computed.myMapForView.get())
},
computed: {
myMapForView: {
// getter
get: function () {
return this.$store.state.myMap
},
// setter
set: function () {
this.$store.dispatch('loadMap')
}
}
}
}
</script>
Which does not work. Any suggestions on the solution approach and specific way to do this is much appreciated.
Error message I get in the browser:
vue.runtime.common.js?d43f:433 TypeError: Cannot read property 'myMapForView' of undefined
at VueComponent.mounted (eval at 162 (0.ce2d9bf….js:21), <anonymous>:8:18)
at callHook (eval at <anonymous> (app.js:794), <anonymous>:2335:19)
at Object.insert (eval at <anonymous> (app.js:794), <anonymous>:2525:5)
at invokeInsertHook (eval at <anonymous> (app.js:794), <anonymous>:4352:28)
at VueComponent.patch [as __patch__] (eval at <anonymous> (app.js:794), <anonymous>:4508:5)
at VueComponent.Vue._update (eval at <anonymous> (app.js:794), <anonymous>:2222:19)
at VueComponent.eval (eval at <anonymous> (app.js:794), <anonymous>:2189:10)
at Watcher.get (eval at <anonymous> (app.js:794), <anonymous>:1652:27)
at Watcher.run (eval at <anonymous> (app.js:794), <anonymous>:1721:22)
at flushSchedulerQueue (eval at <anonymous> (app.js:794), <anonymous>:1539:13)
logError @ vue.runtime.common.js?d43f:433
EDIT:
After changing to this.myMapForView
from this.computed.myMapForView
I got following errormessage in browser:
vue.runtime.common.js?d43f:433
TypeError: Cannot read property 'set' of undefined
at VueComponent.mounted (eval at 162 (0.85b2be9….js:21), <anonymous>:6:22)
at callHook (eval at <anonymous> (app.js:794), <anonymous>:2335:19)
at Object.insert (eval at <anonymous> (app.js:794), <anonymous>:2525:5)
at invokeInsertHook (eval at <anonymous> (app.js:794), <anonymous>:4352:28)
at VueComponent.patch [as __patch__] (eval at <anonymous> (app.js:794), <anonymous>:4508:5)
at VueComponent.Vue._update (eval at <anonymous> (app.js:794), <anonymous>:2222:19)
at VueComponent.eval (eval at <anonymous> (app.js:794), <anonymous>:2189:10)
at Watcher.get (eval at <anonymous> (app.js:794), <anonymous>:1652:27)
at Watcher.run (eval at <anonymous> (app.js:794), <anonymous>:1721:22)
at flushSchedulerQueue (eval at <anonymous> (app.js:794), <anonymous>:1539:13)
logError @ vue.runtime.common.js?d43f:433
It seems to me is new mapboxgl.Map()
is an asynchronous function and in vuex Actions can contain arbitrary asynchronous operations not mutations not from mutations. mutation handler functions must be synchronous.
So you should do new mapboxgl.Map()
in actions like following:
import simple from '../../components/simplestyle'
let mapboxgl = require('mapbox-gl/dist/mapbox-gl.js')
// initial state
const state = {
myMap: {},
mapLoaded: false
}
const mutations = {
loadMap (state, myMap) {
state.myMap = myMap
}
}
const actions = {
loadMap (context) {
'use strict'
mapboxgl.accessToken = 'mysecretmapboxkey'
var myMap = new mapboxgl.Map({
container: 'map',
style: simple,
hash: true,
center: [-74.0073, 40.7124],
zoom: 16
})
context.commit('loadMap', myMap)
}
}
export default {
state,
mutations,
actions
}
Edit:
Given your mouse interactions are causing change in the state, you can have a computed property in you vue instance with getter and setter, like following:
computed: {
myMapForView: {
// getter
get: function () {
return this.$store.state. myMap
},
// setter
set: function (newMap) {
this.$store.commit('loadMap', newMap)
}
}
}
Also check: Vuex store with "strict: true" does not work
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With