Pinia stores imported from npm packages are not reactive or don't share the same context #2676
-
ReproductionApparently, using exported pinia-stores from npm packages doesn't work as expected. There seems to be an issue with either the context pinia is running in (and conflicts with the one of the consuming application) or the reactivity is somehow broken. Steps to reproduce the bugThe reproduction contains multiple steps, as creating a local npm package and use it in your vue application as an import. Let's go through it step by step. Create the local npm packageUsing: Start with the basic steps:
Create a package.json that will take care of the module bundling, entry-point, etc. I use the following one: {
"name": "pinia-test-package",
"version": "1.0.0",
"type": "module",
"files": [
"build"
],
"main": "./build/pinia-test-package.umd.cjs",
"module": "./build/pinia-test-package.js",
"exports": {
".": {
"import": "./build/pinia-test-package.js",
"require": "./build/pinia-test-package.umd.cjs"
}
},
"scripts": {
"build": "vite build"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@vue/reactivity": "^3.4.27",
"pinia": "^2.1.7"
},
"devDependencies": {
"vite": "^5.2.11"
}
} I add a simple pinia store called import { ref } from '@vue/reactivity'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counterStore', () => {
const count = ref(0)
function increment() {
count.value++
}
function decrement() {
count.value--
}
return {
count,
decrement,
increment
}
}) For the import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/counter.js'),
fileName: 'pinia-test-package',
name: 'pinia-test-package'
},
outDir: 'build',
rollupOptions: {
external: ['pinia']
},
sourcemap: true
},
plugins: []
}) Install the package dependencies:
Now build the package:
That will create an output directory, containing all the relevant package files Since the Create the wrapper app
For this, I am using a simple vite/vue3 application. Scaffolding it as the documentation points out:
Then follow the instructions of the CLI:
Now a dev-server will be running at port 🆙 For the ease of testing, I removed the Now, install pinia:
Now, install your local npm package (the
Assuming, that your directories (package & wrapper) are placed side-by-side, as described in the beginning of this section. Install pinia in your import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { createPinia } from 'pinia'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app') In your <script setup>
import { useCounterStore } from 'pinia-test-package'
const store = useCounterStore()
function incrementCounter() {
store.increment()
}
function decrementCounter() {
store.decrement()
}
</script>
<template>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<h2>Counter: {{ store.count }}</h2>
<button @click="incrementCounter">+1</button>
<button @click="decrementCounter">-1</button>
</div>
</template>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style> In the end, your app should look like this: Explanation: The goal is to use the Expected behaviorClicking the buttons should update the pinia-store Actual behaviorWhen clicking the buttons, nothing happens. Here is a short video: Bildschirmaufnahme.2024-05-21.um.19.19.34.movNotice, while inspecting the pinia store by using the vue-dev-tools (using the ones for chrome), the state does not get updated reactively, but only as soon as I reload the state within my dev-tools: Bildschirmaufnahme.2024-05-21.um.19.22.45.movAdditional informationI also tried using the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
Before I dive into fully reproducing this, your vite config states:
Is there a reason you are not externalizing |
Beta Was this translation helpful? Give feedback.
I reproduced your case, both with and without
@vue/reactivity
marked as external. If you add these console.logs, you will see the state does get updated, and theeffect
from@vue/reactivity
does trigger on changes. But usingwatch
fromvue
does not: