['script', {}, darkModeFix],
...(isProduction ? productionHead : []),
],
+
themeConfig: {
repo: 'posva/pinia',
logo: '/logo.svg',
{ 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',
+ },
],
},
{
## 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({
--- /dev/null
+# 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:
+
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"