vuejs / vuex

🗃️ Centralized State Management for Vue.js.
https://vuex.vuejs.org
MIT License
28.42k stars 9.58k forks source link

VueX store loses reactivity if shared using window on page with multiple Vue bundles #2181

Open stam opened 2 years ago

stam commented 2 years ago

Version

3.4.0

Reproduction link

https://github.com/stam/multiple-vue-apps

Steps to reproduce

Clone the mentioned repo npm i npm run serve open ./index.html Click on the count++ buttons

What is expected?

I expect both counters to update and reactivity to be intact

What is actually happening?

Only one counter updates, as the Vuex store in the other app is not reactive


We have 2 vue bundles on the same page. They share their VueX store using window.globalStore, but when you press count++ only one app is updated.

The obvious fix would be to just use 1 vue bundle. However this doesn't work in my company's usecase: We are gradually migrating from a legacy server side rendered application to a SPA. Small parts of the application are being converted to Vue, where the legacy application loads the specific Vue bundles on demand. However multiple Vue bundles can live on the same page, and we want to share some state as we don't want to duplicate API calls.

TimvdEijnden commented 2 years ago

I'm facing the same issue. We can create a new store and call

newStore.registerModule('users', { 
  ...existingStore._modules.root._children.users._rawModule, 
  state: existingStore.state.users}
);

Then the reactivity works. But it's still not ideal and causes issues when using Vuex in strict mode.

Did you find a solution @stam ?

@yyx990803 @kiaking Would there be an option to manually add the reactivity to the 2nd vue instance?

stam commented 2 years ago

@TimvdEijnden I haven't found a fix, we're now just not sharing the store and instead are refactoring to an SPA.

The core issue is probably because reactivity is managed by the Vue singleton, and the Vue instance in bundle B does not keep track of the VueX store in bundle A

rodhoward commented 2 years ago

I'm not sure if what we're experiencing is exactly the same issue but we are trying to lazy load routes (bundles) and then using

 if (store.hasModule(key)) return;
 store.registerModule(key, componentStateObject);

To register the extra route components when the page/route loads.

Its working great except that we seem to lose reactivity on our getters after we register the first dynamic module.

Versions: "vue": "^2.6.14", "vuex": "^3.6.2", "vue-router": "^3.5.3", "@vue/cli-plugin-babel": "^3.12.1", "@vue/cli-plugin-eslint": "^3.12.1", "@vue/cli-plugin-unit-jest": "^4.5.17", "@vue/cli-service": "^4.5.17", "@vue/compiler-sfc": "^3.2.20", "vue-runtime-helpers": "^1.1.2", "vue-template-compiler": "^2.6.14", "vue-template-es2015-compiler": "^1.9.1"

dtorres-sf commented 2 years ago

I have an issue similar to @rodhoward - it started happening when we upgraded to Vue 2.7. Everything seems to work except for reactivity in getters. I tested going back to Vue 2.6.13 and it started working again. In both cases I am using Vuex 3.6.2.