},
{
text: 'Server-Side Rendering (SSR)',
- link: '/ssr.html',
+ link: '/server-side-rendering.html',
},
{
text: 'Cookbook',
# Actions
-Actions are the equivalent of [methods](https://v3.vuejs.org/guide/data-methods.html#methods) in components. They can be defined with the `actions` property in `defineStore()` and it's a perfect place to define business logic:
+Actions are the equivalent of [methods](https://v3.vuejs.org/guide/data-methods.html#methods) in components. They can be defined with the `actions` property in `defineStore()` and they are perfect to define business logic:
```js
export const useStore = defineStore({
})
```
-Like [getters](./getters.md), actions get access to the _whole store instance_ through `this` with full typing (and autocompletion ✨) support.
+Like [getters](./getters.md), actions get access to the _whole store instance_ through `this` with **full typing (and autocompletion ✨) support**.
Actions are invoked like methods:
})
```
-Like [actions](./actions.md), getters get access to the _whole store instance_ through `this` with full typing (and autocompletion ✨) support.
+Like [actions](./actions.md), getters get access to the _whole store instance_ through `this` with **full typing (and autocompletion ✨) support**.
Then you can access the getter directly on the store instance:
## Accessing other stores
+To access a different store, you can directly _use_ the other store inside of a `getter`
+
```js
+import { useOtherStore } from './other-store'
+
export const useStore = defineStore({
id: 'main',
state: () => ({
})
```
-The `id` is necessary and is used by `pinia` to connect the store to the devtools.
+The `id` is necessary and is used by `pinia` to connect the store to the devtools. Naming the returned function _use..._ is a convention across composables to make its usage idiomatic.
## 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 automatically allow your bundle to code split.
+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).
-Avoid calling `useStore()` outside of a `setup()` function:
+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:
```js
import { createRouter } from 'vue-router'
})
```
-Instead, call `useStore()` inside functions that are called after `app.use(pinia)`:
+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) => {
```
:::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](./server-side-rendering.md).
+When dealing with Server Side Rendering, you will have to pass the `pinia` instance to `useStore()`. Read more about this in the [SSR guide](/server-side-rendering.md).
:::
-Once the store is instantiated, you can access any property defined in `state` and `getters` directly on the store, similar to `data` and `computed` properties in a vue component.
-
-```js
-// inside a component
-export default defineComponent({
- setup() {
- const store = useStore()
- const text = store.name // "eduardo"
- store.doubleCount // 2
-
- return {
- text, // will always be "eduardo"
- doubleValue: computed(() => store.doubleValue), // reactive value
- }
- },
-})
-```
+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:
```ts
export default defineComponent({
setup() {
+ const store = useStore()
// ❌ This won't work because it breaks reactivity
// it's the same as destructuring from `props`
- const { name, doubleCount } = useStore()
- return { name, doubleCount }
+ const { name, doubleCount } = store
+
+ name // "eduardo"
+ doubleCount // 2
+
+ return {
+ // will always be "eduardo"
+ name,
+ // will always be 2
+ doubleCount
+ // this one will be reactive
+ doubleValue: computed(() => store.doubleCount),
+ }
},
})
```
# State
-The state is, most of the time, the central part of your store. People often start by defining the state that represents their app. In Pinia the state is defined as a function that returns the initial state. \_This allows Pinia to work in both Server and Client Side.
+The state is, most of the time, the central part of your store. People often start by defining the state that represents their app. In Pinia the state is defined as a function that returns the initial state. This allows Pinia to work in both Server and Client Side.
```js
import { defineStore } from 'pinia'
const useStore = defineStore({
id: 'storeName',
+ // can also be defined with an arrow function if you prefer that syntax
state() {
return {
// all these properties will have their type inferred automatically
## Accessing the `state`
-You can directly read and write to the state by accessing it through the `store` instance:
+By default, you can directly read and write to the state by accessing it through the `store` instance:
```js
+const store = useStore()
+
store.counter++
```
+<!-- TODO: disable this with `strictMode` -->
+
or call the method `$patch` that allows you apply multiple changes at the same time with a partial `state` object:
```ts
store.$patch({
- counter: -1,
+ counter: store.counter + 1,
name: 'Abalam',
})
```
-The main difference here is that `$patch` allows you to group multiple changes into one single entry in the devtools.
+<!-- TODO: disable this with `strictMode`, `{ noDirectPatch: true }` -->
+
+The main difference here is that `$patch()` allows you to group multiple changes into one single entry in the devtools. Note **both, direct changes to `state` and `$patch()` appear in the devtools**.
## Replacing the `state`
-Simply set your store `$stet` property to a new object:
+You can replace the whole state of a store by setting its `$state` property to a new object:
```ts
store.$state = { counter: 666, name: 'Paimon' }
```
:::tip
-Install Pinia v2 for Vue 3 `pinia@next` and Pinia v1 `pinia@latest` for Vue 2.
+`pinia@next` install Pinia v2 for Vue 3. If your app is using Vue 2, you need to install Pinia v1: `pinia@latest`.
:::
Create a pinia (the root store) and pass it to app:
app.use(createPinia())
```
-If you are using Vue 2, do:
+If you are using Vue 2, you also need to install a plugin and inject the created `pinia` at the root of the app:
```js
import { createPinia, PiniaPlugin } from 'pinia'
new Vue({
el: '#app',
// other options...
+ // ...
+ // note the same `pinia` instance can be used across multiple Vue apps on
+ // the same page
pinia,
})
```
## What is a Store?
-A Store (like Pinia) is an entity holding state and business logic that isn't bound to your Component tree. In other words, **it hosts global state**. It's a bit like a component that is always there and that everybody can read off and write to. It has **three concepts**, the [state](./state.md), [getters](./getters.md) and [actions](./actions.md).
+A Store (like Pinia) is an entity holding state and business logic that isn't bound to your Component tree. In other words, **it hosts global state**. It's a bit like a component that is always there and that everybody can read off and write to. It has **three concepts**, the [state](./core-concepts/state.md), [getters](./core-concepts/getters.md) and [actions](./core-concepts/actions.md) and it's safe to assume these concepts are the equivalent of `data`, `computed` and `methods` in components.
## When should I use a Store
export const useCounter = defineStore({
id: 'counter',
- state: () => ({ count: 0 }),
+ state() {
+ return { count: 0 }
+ },
+ // could also be defined as
+ // state: () => ({ count: 0 })
})
```
}
```
+<!-- TODO: or if you prefer using the options api, use `mapStores` -->
+
## Why _Pinia_
Pinia (pronounced like `/peenya/` in English) is is the closest word to _piña_ (_pineapple_ in Spanish) that is a valid package name. A pineapple is in reality a group of individual flowers that join together to create a multiple fruit. Similar to stores, each one is born individually, but they are all connected at the end. It's also a delicious tropical fruit indigenous to South America.
## A more realistic example
-Here is a more complete example of the API you will be using with Pinia **with types** even in JavaScript:
+Here is a more complete example of the API you will be using with Pinia **with types even in JavaScript**. For some people this might be enough to get started without reading further but we still recommend checking the rest of the documentation or even skipping this example and coming back once you have read about all of the _Core Concepts_.
```js
import { defineStore } from 'pinia'
-# Server Side Rendering
+# Server Side Rendering (SSR)
Creating stores with Pinia should work out of the box for SSR as long as you call your `useStore()` functions at the top of `setup` functions, `getters` and `actions`: