lmiller1990 / design-patterns-for-vuejs-source-code

Soure code for my book "Design Patterns for Vue.js": https://lachlan-miller.me/design-patterns-for-vuejs
126 stars 28 forks source link

inject('store') in the provide-inject example is undefined #1

Closed Duncank closed 3 years ago

Duncank commented 3 years ago

I'm trying to make use of the useStore example in the provide-inject folder, but the useStore import returns undefined, so the getState and addUser methods are not available either.

I'm not sure how to solve this myself, so hopefully you can help with this!

lmiller1990 commented 3 years ago

Hi! Sorry, I did not se your issue. You can tag me so I can get a notification. @Duncank.

Can you provide an example of code that isn't working? As far as I can see all the code is okay (tests all passing).

Duncank commented 3 years ago

No worries! I've created an example here: Codesandbox.

It looks to me like the injected store doesn't work, but the exported store does. The tests only seem to use the exported store, and not the injected one, so that is probably why they aren't catching this.

lmiller1990 commented 3 years ago

Right, I see the problem. When you use inject, you need to have called provide with the same key (in this case 'store') in some component higher in the hierarchy. I forked and updated your example, see here.

Basically the change I made was in main.js:

import { createApp } from "vue";
import App from "./App.vue";
import { store } from "./store";

const app = createApp(App);
/** This is the important part **/
app.provide("store", store);

app.mount("#app");

By doing provide('store', store) at the top level, any component that has inject('store') called will recursively search upwards until it finds somewhere provide was called with a matching key. The Vue.js 3 docs have more details.

The reason it works in the example in the book is because we do provide in the global key in Vue Test Utils. Under the hood, this is doing the same thing I described above - it just calls app.provide on each of the values passed in global.provide. You can see that here in the source code for Vue Test Utils v2.

Hopefully that helps, let me know if you have any more questions. Thanks for checking out my content!

Duncank commented 3 years ago

Thank you for your response and time you've invested in to this! Your example makes it clear how to use this!