Vue3 Webcomponents share Pinia Store #2620
Replies: 3 comments 4 replies
-
I run into the same problem. I hve tried to avoid Pinia and use a standard Vue reactive as described here: https://vuejs.org/guide/scaling-up/state-management.html#simple-state-management-with-reactivity-api Unfortunately, the problem is exaxtely the same: Multiple customElements on the same page share the same state. |
Beta Was this translation helpful? Give feedback.
-
A solutions using random store names and provide/inject :
|
Beta Was this translation helpful? Give feedback.
-
Pinia uses an active instance, that is injected into the Vue application. If your components are part of the same vue app and use Also ask yourself, do you really need pinia for this? If you want a 'store', you could just create a reactive object and expose some methods to modify this state in a composable and return that. Initially, when I learned the new Vue active instance design, I ran into similar issues because it requires you to be aware that code behaves based on whatever code is considered 'active' at that moment. So my answers to your questions would be:
Yes this is intended behaviour. Because the web component instances are explicitly opting into the global shared state by using a globally shared store. There is no border between web components, they are just components in the same app instance.
The article seems to be using a hack to accomplish the idea of a reusable store, but really its just using the wrong tool for the job. If this is still an active problem let me know, and I'll try and write out an example of using a composable that implements your requirements. |
Beta Was this translation helpful? Give feedback.
-
During work I came across the need to embed a web component built with Vue3 and Vue's
defineCustomElement
function into another website more than one time.The web component is rather complex with one "root level" Vue file that uses several other normal Vue components, so I made a simple reproducer that showcases my finding: https://github.com/m1rm/vue3-webcomponent-reproducer/tree/main
Although it is made clear in the pinia documentation, that pinia stores are global (that's why we use/want/need stores), I did not expect the web components to share state.
The only way I found (apart from encapsulating the web component in an iFrame) to separate the stores between web components would be to pass a unique ID to the store upon instance creation of the web component.
--> Edit: I added a provide/inject example in the reproducer and I think that would work, too.
For the real-world use case of my company that would mean to also pass this unique ID generated in the "root level" Vue-file down to all child components via a prop (a technique called "prop drilling"). But this is against the intention/idea of using a store and we then could not use a store at all (with all the downs coming from not using one regarding shared state within the web component). Also, using Vue's provide/inject is a document Vue-way but I would rather expect Vue to handle scoping everything to the web component for me.
I wonder if
a) the behavior of pinia is intended for surpassing the borders of web components
b) there is any better solution out there (preferably without the use of internal APIs like showcased here https://rimdev.io/vue-3-custom-elements)
Related discussions: #840 -> leaves out the web component part as far as I understood
Beta Was this translation helpful? Give feedback.
All reactions