-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v4 reactive getters behaviour appears to have changed for nested methods? #1890
Comments
@songololo This might be related to #1889. Could you test with Vuex 4.0.0-RC.2? |
I am still encountering the same issue on |
Oh, OK. Hmmm... let me look into it. |
@songololo OK, I can't reproduce the issue. I've tried first defining <template>
<div id="app">
<button @click="setInstance">SET INSTANCE</button>
<p>{{ zoom }}</p>
</div>
</template>
<script>
class MapInstance {
getZoom() {
return 'Zoom!'
}
}
export default {
computed: {
zoom () {
return this.$store.getters.zoom
}
},
methods: {
setInstance () {
this.$store.commit('setMapInstance', new MapInstance())
}
}
}
</script> When you click |
Thanks. I added a reproduction here: I am trying to use a Mapbox instance via the store, which is something I used to be able to do in Vue v2 with the old |
@songololo Thank you for the code! OK, so I've run the code, and got this.
I wondered maybe you wanted to {
state: {
obj: {
valueA: 1,
edit () {
this.valueA++
}
}
}
} Then it worked. The Could you describe your issue a little more so I understand what I'm trying to look at. Also, if it would be very helpful if you could also provide Vuex 3 version of the working code as well 🙏 |
Thanks for looking: I've created a repo using Vue 2 with Vuex 3 over here: https://github.com/songololo/test-vuex-3, which shows the reactive behaviour in action. |
@songololo Thanks for the reproduction. Now I see what is going on. Indeed Vuex 3 is updating the state. I did few tests. If we assign a new class, and then update the state, it will be reactively updated. Like this. // store.js
import { createStore } from 'vuex'
class Obj {
constructor() {
this.valueA = 1
}
getA() {
return this.valueA
}
update() {
this.valueA++
}
}
export default createStore({
state: {
obj: null
},
mutations: {
setObj(state) {
state.obj = new Obj()
}
},
actions: {
initObj({ commit }) {
commit('setObj')
}
},
getters: {
getObjA: (state) => {
return state.obj ? state.obj.getA() : 'nope'
}
}
}) This is essentially the very simple version of <script>
import { computed, onMounted } from 'vue'
import { useStore } from 'vuex'
export default {
name: 'App',
setup() {
const store = useStore()
onMounted(async () => {
await store.dispatch('initObj')
// Update state value on every scroll.
window.addEventListener('scroll', (s) => {
store.state.obj.update()
})
})
const getA = computed(() => {
return store.state.obj ? store.state.obj.getA() : 'nope'
})
return {
mapDiv,
getA
}
}
}
</script> So, "nested methods" is working as same as Vuex 3 at this point. However, I still don't know why This issue also happens when using plain We need a more minimal reproduction code for Request to youQ. Would it be possible for you to dig into What happens from here onSince it's stated here at docs that:
It is best to not store this kind of class instance to state in the first place, I'll recommend you to modify your code to change how you handle the Map instance. Because of this, I would suppose this issue will not be handled in the near future. Also, if we were to address this issue, the change has to be made in Vue side, not in Vuex. However, I'm not saying this should never be addressed. At the moment, I don't know. If we can determine what is the root cause of the issue, we might find a way out. If anyone can help us with debugging the Map instance behaviours, it would be really nice 🙌 |
Thanks @kiaking For now I've changed approach to work with the new behaviour: I've attached event watchers to the Map object and these, in turn, update the state when the map is moved (and I can then plumb the reactive getters to those instead). Regarding
So, the action is happening at two levels deep: Map -> transform -> zoom |
Great to hear you found a way out!
Yeah... though it's strange. I don't see why nested function wouldn't work. Maybe we can come back and check if something would change in Vue 3 👀 |
it('getters', () => {
const fn = jest.fn()
const store = new Vuex.Store({
state: {
a: 0
},
getters: {
state: state => {
fn()
return state.a > 0 ? 'hasAny' : 'none'
}
},
mutations: {
[TEST] (state, n) {
state.a += n
}
},
actions: {
check ({ getters }, value) {
// check for exposing getters into actions
expect(getters.state).toBe(value)
}
}
})
expect(store.getters.state).toBe('none')
store.dispatch('check', 'none')
store.commit(TEST, 1)
expect(store.getters.state).toBe('hasAny')
expect(store.getters.state).toBe('hasAny')
expect(store.getters.state).toBe('hasAny')
expect(fn.mock.calls.length).toBe(5)
}) The above issue occurred from |
What problem does this feature solve?
I used to be able to apply a reactive getter to a nested method inside an object instance stored in my v3
vuex
state, but this doesn't appear to work anymore in v4.In my case it was a
mapbox
instance which was created and then stored inside thevuex
v3 store's state. I could then share this instance amongst various components and could also watch the instance for changes via reactive getters.For example:
The same approach no longer works in
vuex
v4.What does the proposed API look like?
I'm assuming something has changed in the internals of
vuex
v3 vs. v4: is there a way to deliberately expose certain nested properties or methods to reactive getters invuex
v4? Or else to enable the previous functionality?The text was updated successfully, but these errors were encountered: