From: Eduardo San Martin Morote Date: Tue, 20 Jul 2021 09:34:16 +0000 (+0200) Subject: docs: simplify store usage X-Git-Tag: v2.0.0-rc.0~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3eeefa0830cc3c3d7f2cda8bac8cb5daefcb0dde;p=thirdparty%2Fvuejs%2Fpinia.git docs: simplify store usage Close #563 --- diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index 330c2151..f2f4076f 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -121,6 +121,7 @@ module.exports = { ['script', {}, darkModeFix], ...(isProduction ? productionHead : []), ], + themeConfig: { repo: 'posva/pinia', logo: '/logo.svg', @@ -191,6 +192,10 @@ module.exports = { { text: 'Getters', link: '/core-concepts/getters.html' }, { text: 'Actions', link: '/core-concepts/actions.html' }, { text: 'Plugins', link: '/core-concepts/plugins.html' }, + { + text: 'Stores outside of components', + link: '/core-concepts/outside-component-usage.html', + }, ], }, { diff --git a/docs/core-concepts/index.md b/docs/core-concepts/index.md index fe0c295c..96e5855a 100644 --- a/docs/core-concepts/index.md +++ b/docs/core-concepts/index.md @@ -16,43 +16,30 @@ The `id` is necessary and is used by `pinia` to connect the store to the devtool ## Using the store -We are _defining_ a store because the store won't be created until `useStore()` is called inside of `setup()`. You can define as many stores as you want and you should define each store in a different file to get the most out of pinia (like automatically allow your bundle to code split). - -It's not possible to call `useStore()` outside of a `setup()` function. Here is an example using a store inside of a navigation guard with Vue Router: +We are _defining_ a store because the store won't be created until `useStore()` is called inside of `setup()`: ```js -import { createRouter } from 'vue-router' -const router = createRouter({ - // ... -}) +import { useStore } from '@/stores/counter' -// ❌ Depending on where you do this it will fail -const store = useStore() +export default { + setup() { + const store = useStore() -router.beforeEach((to, from, next) => { - if (store.isLoggedIn) next() - else next('/login') -}) + return { + // you can return the whole store instance to use it in the template + store, + } + }, +} ``` -Instead, make sure to call `useStore()` inside functions that are called after your application is mounted (`app.mount()` or `new Vue()`): - -```js -router.beforeEach((to) => { - // ✅ This will work because the router starts its navigation after pinia is installed - const store = useStore() - - if (to.meta.requiresAuth && !store.isLoggedIn) return '/login' -}) -``` +You can define as many stores as you want and **you should define each store in a different file** to get the most out of pinia (like automatically allow your bundle to code split and TypeScript inference). -:::tip -When dealing with Server Side Rendering, you will have to pass the `pinia` instance to `useStore()`. Read more about this in the [SSR guide](/ssr/index.md). -::: +If you are not using `setup` components yet, [you can still use Pinia with _map helpers_](../cookbook/options-api.md). Once the store is instantiated, you can access any property defined in `state`, `getters`, and `actions` directly on the store. We will see these in detail in the next pages but autocompletion will help you. -`store` in an object wrapped with `reactive`, meaning there is no need to write `.value` after getters but, like `props` in `setup`, we cannot destructure it: +Note that `store` in an object wrapped with `reactive`, meaning there is no need to write `.value` after getters but, like `props` in `setup`, **we cannot destructure it**: ```js export default defineComponent({ diff --git a/docs/core-concepts/outside-component-usage.md b/docs/core-concepts/outside-component-usage.md new file mode 100644 index 00000000..0b4fd516 --- /dev/null +++ b/docs/core-concepts/outside-component-usage.md @@ -0,0 +1,60 @@ +# Using a store outside of a component + +Pinia stores rely on the `pinia` instance to share the same store instance across all calls. Most of the time, this works out of the box by just calling your `useStore()` function. For example, in `setup()`, you don't need to do anything else. But things are a bit different outside of a component. +Behind the scenes, `useStore()` _injects_ the `pinia` instance you gave to your `app`. This means that if the `pinia` instance cannot be automatically injected, you have to manually provide it to the `useStore()` function. +You can solve this differently depending on the kind of application you are writing. + +## Single Page Applications + +If you are not doing any SSR (Server Side Rendering), any call of `useStore()` after installing the pinia plugin with `app.use(pinia)` will work: + +```js +import { useUserStore } from '@/stores/user' +import { createApp } from 'vue' +import App from './App.vue' + +// ❌ fails because it's called before the pinia is created +const userStore = useUserStore() + +const pinia = createPinia() +const app = createApp(App) +app.use(pinia) + +// ✅ works because the pinia instance is now active +const userStore = useUserStore() +``` + +The easiest way to ensure this is always applied is to _defer_ calls of `useStore()` by placing them inside functions that will always run after pinia is installed. + +Let's take a look at this example of using a store inside of a navigation guard with Vue Router: + +```js +import { createRouter } from 'vue-router' +const router = createRouter({ + // ... +}) + +// ❌ Depending on the order of imports this will fail +const store = useStore() + +router.beforeEach((to, from, next) => { + // we wanted to use the store here + if (store.isLoggedIn) next() + else next('/login') +}) + +router.beforeEach((to) => { + // ✅ This will work because the router starts its navigation after + // the router is installed and pinia will be installed too + const store = useStore() + + if (to.meta.requiresAuth && !store.isLoggedIn) return '/login' +}) +``` + +## SSR Apps + +When dealing with Server Side Rendering, you will have to pass the `pinia` instance to `useStore()`. This prevents pinia from sharing global state between different application instances. + +There is a whole section dedicated to it in the [SSR guide](/ssr/index.md), this is just a short explanation: + diff --git a/yarn.lock b/yarn.lock index 883a973a..f8e1fc79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2266,9 +2266,9 @@ dot-prop@^5.1.0: is-obj "^2.0.0" electron-to-chromium@^1.3.723: - version "1.3.779" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.779.tgz#de55492a756deec63424f89fbe62aec9776f0e6d" - integrity sha512-nreave0y/1Qhmo8XtO6C/LpawNyC6U26+q7d814/e+tIqUK073pM+4xW7WUXyqCRa5K4wdxHmNMBAi8ap9nEew== + version "1.3.780" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.780.tgz#f946e10dc0005a3b59b9afa2d2c92f5c421f7fc5" + integrity sha512-2KQ9OYm9WMUNpAPA/4aerURl3hwRc9tNlpsiEj3Y8Gf7LVf26NzyLIX2v0hSagQwrS9+cWab+28A2GPKDoVNRA== emittery@^0.7.1: version "0.7.2"