vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.69k stars 8.33k forks source link

Values provided from app are `undefined` when using `inject` in Pinia setup store #11602

Closed Anoesj closed 3 months ago

Anoesj commented 3 months ago

Vue version

3.4.37

Link to minimal reproduction

https://stackblitz.com/edit/github-tg21by-ju6avc?file=components%2FHi.vue

Steps to reproduce

Injections in Pinia stores are broken as of Vue 3.4.37. I'm assuming this to be a regression caused by this PR: https://github.com/vuejs/core/pull/11502, as it seems to be the only change in 3.4.37 related to the provide/inject system.

Note that the reproduction is made with the Nuxt starter template, as I thought this was a Nuxt bug at first. Running Nuxt without SSR results in the same bug, so I'm expecting this to be a bug solely related to Vue, not nuxt, pinia and/or @pinia/nuxt.

Repro for 3.4.37 (injections always undefined): see repro link above Repro for 3.4.36 (injections working as expected): https://stackblitz.com/edit/github-tg21by-mkqgva?file=components%2FHi.vue

What is expected?

Values provided by app.vue are available in the Pinia store by using inject.

What is actually happening?

All injected values are undefined.

System Info

System:
    OS: Linux 6.5 Ubuntu 22.04.4 LTS 22.04.4 LTS (Jammy Jellyfish)
    CPU: (16) x64 AMD Ryzen 7 5800H with Radeon Graphics
    Memory: 7.20 GB / 13.49 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 20.12.2 - ~/.local/share/pnpm/node
    npm: 10.5.0 - ~/.local/share/pnpm/npm
    pnpm: 9.7.0 - ~/.local/share/pnpm/pnpm
    bun: 1.1.17 - ~/.bun/bin/bun
  Browsers:
    Chrome: 127.0.6533.99

Note that the bug is also present in the Stackblitz environment, so I don't think this is a system-specific problem.

Any additional comments?

No response

Gianthard-cyh commented 3 months ago

You are correct that this issue is indeed related to #11502, but I believe the reproduction you provided demonstrates the expected behavior outlined in the Vue and Pinia documentation.

In the Pinia documentation, it states:

Setup stores are also able to rely on globally provided properties like the Router or the Route. Any property provided at the App level can be accessed from the store using inject(), just like in components.

Before #11502 was merged, the component context had a higher priority than the App context when using inject(). As a result, it was possible to inject component-provided properties in Pinia, which was incorrect. Since pinia is a global state manager, it seems not so meaningful to inject a state provided by a component instead of a globally provided state to a pinia store. The expected behavior is that Pinia's inject() should retrieve provides from the App context. After #11502 was merged, this behavior is now correct, so I believe the erroneous reproduction you provided actually reflects the expected behavior.

If you want to use inject() in Pinia, you should consider using app.provide instead of using provide within the setup function of the App.vue component.

Anoesj commented 3 months ago

Hmm, okay. This hasn't been documented anywhere as far as I know. Nuxt is very "app.vue-oriented", so I don't think I'm wrong to assume this would have worked. So what is the correct scope to provide into? It's really hard for people to understand all the scopes that come into play in a Vue app. Do I use useNuxtApp().provide? And in what file? At this point I'm just wondering how people find out about stuff like this. Vue is full of things people should apparently "just know". Even after 6 years, I still find out things about Vue the hard way.

edison1105 commented 3 months ago

I agree with @Gianthard-cyh. According to pinia's documentation, the current behavior is expected.

useNuxtApp().vueApp in app.vue

<script setup lang="ts">
const app = useNuxtApp().vueApp;
app.provide('test', 'hi as primitive');
app.provide('testRef', ref('hi as ref'));
</script>

see https://stackblitz.com/edit/github-tg21by-wjhhbr?file=app.vue

Anoesj commented 3 months ago

Fantastic, thanks for the quick assistance! Would it be a good idea to make a note of this in the changelog? While I understand you've actually fixed a problem with #11502, it can be perceived as a breaking change as well.