Skip to content
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

Getters - Reactivity broken after registering new module #2197

Open
lordolive opened this issue Nov 15, 2022 · 12 comments · May be fixed by #2201 or #2234
Open

Getters - Reactivity broken after registering new module #2197

lordolive opened this issue Nov 15, 2022 · 12 comments · May be fixed by #2201 or #2234

Comments

@lordolive
Copy link

Version

Vue: 3.2.45
Vuex: 4.1.0

Reproduction link

https://github.com/lordolive/vuex4-getters-reactivity

Steps to reproduce

  • Clone the repo
  • npm i
  • npm run dev

Then in website :

  • Click the first button, the getter is reactive and the count increments.
  • Click the second button to register the module
  • Click the first button, the getter is no longer reactive and the count does not change.

What is expected?

The getter reactivity should still work and the count in the button should increment.

What is actually happening?

The getter accessed before the call to this.$store.registerModule() is no longer reactive, but the one that was not accessed before is still reactive

image

Additionnal comments

I first tried with MapGetters and had the same problem.
Using $store.getters.count directly in the template solve the issue, but in my real application with multiple modules it is simply not pratical, especially considering that we are migrating a lot of code from Vue 2 which was working with mapGetters.

@jkosir
Copy link

jkosir commented Nov 22, 2022

Experiencing the same issue, the problem is the replacement and stopping of store._scope in resetStoreState which is called when registering a new module.

This stops currently active effectScope (store._scope) onto which all getters are bound and registers them again, which will cause any effect (computed, watch, e.g. count1 in reproduction example linked above) to become inactive and simply stop reacting to state changes.

A workaround (non-feasible, but still) is to subscribe to onScopeDispose of store._scope and re-register computed/watch effects you need, e.g. like this:

store._scope.run(() => {
	installWatcher()
})

function installWatcher () {
	onScopeDispose(() => {
	    installWatcher()
	})
	watch(() => ...)
})

@kiaking @posva (since you originally added and reviewed this in #1883) unless I'm missing something the replacement of store._scope shouldn't be needed (here)? If this is done then any effect referencing getters will become inactive and afaik there's no way to reactivate it from store.

EDIT: Ah I see the entire state is also replaced, therefore all computed-wrapped getters need to be reinitialized too. But any existing effect linked to a store getter will then stop working, as it will still be linked to previous (now inactive) computed-wrapped getter.

@catalin-bratu
Copy link

Any ETA till this bug will get fixed?

@4refael
Copy link

4refael commented Dec 30, 2022

This is a serious regression.

@136759790
Copy link

136759790 commented Mar 1, 2023

same problem

@jaredplowman
Copy link

We're in the same boat, we narrowed it down to this change in resetStoreState as well

Object.defineProperty(store.getters, key, {
   /*good->*/     get: () => computedObj[key](),
   /*bad->*/     // get: () => computedCache[key].value,
        enumerable: true // for local getters
      });

Interestingly enough any modules registered after the initial store still work without issue. We are rolling back to 4.0.2 for now.

@ricardobuquet
Copy link

Same problem here, this is really annoying

@danielmiksavmlyr
Copy link

Same problem for me - Vue 3.3.4 + Vuex 4.1.0. Thank you @jaredplowman for the tip with downgrading package. It solves this particular issue.

alecgibson added a commit to reedsy/vuex that referenced this issue Aug 31, 2023
Fixes vuejs#2197

At the moment, when registering a dynamic module, we call
`resetStoreState()` just to register the getters for the new module.

It seems unnecessary to reset the entire store state in this case, and
this actually also leads to [other issues][1].

This change is based on the test case added in
vuejs#2201

The approach taken in this change is to refactor the getter registration
into its own function, and call that new method when registering a
dynamic module instead of resetting the store state.

[1]: vuejs#2197
alecgibson added a commit to reedsy/vuex that referenced this issue Aug 31, 2023
Fixes vuejs#2197

At the moment, when registering a dynamic module, we call
`resetStoreState()` just to register the getters for the new module.

It seems unnecessary to reset the entire store state in this case, and
this actually also leads to [other issues][1].

This change is based on the test case added in
vuejs#2201

The approach taken in this change is to refactor the getter registration
into its own function, and call that new method when registering a
dynamic module instead of resetting the store state.

[1]: vuejs#2197
alecgibson added a commit to reedsy/vuex that referenced this issue Sep 1, 2023
Fixes vuejs#2197

At the moment, when registering a dynamic module, we call
`resetStoreState()` just to register the getters for the new module.

It seems unnecessary to reset the entire store state in this case, and
this actually also leads to [other issues][1].

This change is based on the test case added in
vuejs#2201

The approach taken in this change is to refactor the getter registration
into its own function, and call that new method when registering a
dynamic module instead of resetting the store state.

[1]: vuejs#2197
@Super-Chama
Copy link

Tracking the issue from #2217
It's unsettling why such crucial issue is not fixed still. aside from rolling back to 4.0.2 other way to fix this will be using functional getters. since functional getters are not cached by default they seems to work fine.

@renatodeleao
Copy link

Just stumbled upon this. A coworker upgraded the package while I was doing a feature branch, had a mini panic attack when sync and a lot of things suddenly stopped working after visiting a very specific view — the one with dynamic modules.

Rollback to v4.0.2 fixes it.

I understand that vuex is "sunsetted" and we should move to pinia, but unfortunately I already spent the refactor budget migrating to vue@3.

Thanks OP et al 🙏

@zangab
Copy link

zangab commented Jul 9, 2024

ANY updates?!?! this is actually a BIG issue.

@beocaca
Copy link

beocaca commented Sep 11, 2024

Recently, I have been migrating to vue@3, but it's breaking a lot of getters after registering new module.
With a small refactor budget on a large project, my solution, unfortunately, has been to refactor everything in the getters.
I don't use mapGetters anymore—it causes too many issues
🥲😭😓

export const getUserProfile = (state) => () => { return state.user; };

computed: getUserProfile() { return this.$store.getters["getUserProfile"](); },

@weier910
Copy link

weier910 commented Sep 11, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet