添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Skip to content

Plugins

Pinia stores can be fully extended thanks to a low level API. Here is a list of things you can do:

  • Add new properties to stores
  • Add new options when defining stores
  • Add new methods to stores
  • Wrap existing methods
  • Intercept actions and its results
  • Implement side effects like Local Storage
  • Apply only to specific stores

Plugins are added to the pinia instance with pinia.use() . The simplest example is adding a static property to all stores by returning an object:

This is useful to add global objects like the router, modal, or toast managers.

Introduction

A Pinia plugin is a function that optionally returns properties to be added to a store. It takes one optional argument, a context :

This function is then passed to pinia with pinia.use() :

Plugins are only applied to stores created after the plugins themselves, and after pinia is passed to the app , otherwise they won't be applied.

Augmenting a Store

You can add properties to every store by simply returning an object of them in a plugin:

You can also set the property directly on the store but if possible use the return version so they can be automatically tracked by devtools :

Any property returned by a plugin will be automatically tracked by devtools so in order to make hello visible in devtools, make sure to add it to store._customProperties in dev mode only if you want to debug it in devtools:

Note that every store is wrapped with reactive , automatically unwrapping any Ref ( ref() , computed() , ...) it contains:

This is why you can access all computed properties without .value and why they are reactive.

Adding new state

If you want to add new state properties to a store or properties that are meant to be used during hydration, you will have to add it in two places :

  • On the store so you can access it with store.myState
  • On store.$state so it can be used in devtools and, be serialized during SSR .

On top of that, you will certainly have to use a ref() (or other reactive API) in order to share the value across different accesses:

Note that state changes or additions that occur within a plugin (that includes calling store.$patch() ) happen before the store is active and therefore do not trigger any subscriptions .

WARNING

If you are using Vue 2 , Pinia is subject to the same reactivity caveats as Vue. You will need to use Vue.set() (Vue 2.7) or set() (from @vue/composition-api for Vue <2.7) for when creating new state properties like secret and hasError :

Resetting state added in plugins

By default, $reset() will not reset state added by plugins but you can override it to also reset the state you add:

Adding new external properties

When adding external properties, class instances that come from other libraries, or simply things that are not reactive, you should wrap the object with markRaw() before passing it to pinia. Here is an example adding the router to every store:

Calling $subscribe inside plugins

You can use store.$subscribe and store.$onAction inside plugins too:

Adding new options

It is possible to create new options when defining stores to later on consume them from plugins. For example, you could create a debounce option that allows you to debounce any action:

The plugin can then read that option to wrap actions and replace the original ones:

Note that custom options are passed as the 3rd argument when using the setup syntax:

TypeScript

Everything shown above can be done with typing support, so you don't ever need to use any or @ts-ignore .

Typing plugins

A Pinia plugin can be typed as follows:

Typing new store properties

When adding new properties to stores, you should also extend the PiniaCustomProperties interface.

It can then be written and read safely:

PiniaCustomProperties is a generic type that allows you to reference properties of a store. Imagine the following example where we copy over the initial options as $options (this would only work for option stores):

We can properly type this by using the 4 generic types of PiniaCustomProperties :

TIP

When extending types in generics, they must be named exactly as in the source code . Id cannot be named id or I , and S cannot be named State . Here is what every letter stands for:

  • S: State
  • G: Getters
  • A: Actions
  • SS: Setup Store / Store

Typing new state

When adding new state properties (to both, the store and store.$state ), you need to add the type to PiniaCustomStateProperties instead. Differently from PiniaCustomProperties , it only receives the State generic:

Typing new creation options

When creating new options for defineStore() , you should extend the DefineStoreOptionsBase . Differently from PiniaCustomProperties , it only exposes two generics: the State and the Store type, allowing you to limit what can be defined. For example, you can use the names of the actions:

TIP

There is also a StoreGetters type to extract the getters from a Store type. You can also extend the options of setup stores or option stores only by extending the types DefineStoreOptions and DefineSetupStoreOptions respectively.

Nuxt.js

When using pinia alongside Nuxt , you will have to create a Nuxt plugin first. This will give you access to the pinia instance:

INFO

The above example is using TypeScript, you have to remove the type annotations PiniaPluginContext and Plugin as well as their imports if you are using a .js file.

Nuxt.js 2

If you are using Nuxt.js 2, the types are slightly different: