A Typescript-ready Vuex plugin that enables you to save the state of your app to a persisted storage like Cookies or localStorage.
Table of contents generated with markdown-toc
filter functionreducer functionnpm install --save vuex-persist
or
yarn add vuex-persist
target: es5This module is distributed in 3 formats
/dist/umd/index.js in es5 format/dist/cjs/index.js in es2015 format/dist/esm/index.js in es2015 formatWhen using with Webpack (or Vue CLI 3), the esm file gets used by default.
If your project has a es6 or es2015 target, you're good, but if
for backwards compatibility, you are compiling your project to es5 then
this module also needs to be transpiled.
To enable transpilation of this module
// in your vue.config.js
module.exports = {
/* ... other config ... */
transpileDependencies: ['vuex-persist']
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuex-persist"></script>
This is a plugin that works only on the client side. So we'll register it as a ssr-free plugin.
// Inside - nuxt.config.js
export default {
plugins: [
{ src: '~/plugins/vuex-persist', ssr: false }
]
}
// ~/plugins/vuex-persist.js
import VuexPersistence from 'vuex-persist'
export default ({ store }) => {
new VuexPersistence({
/* your options */
}).plugin(store);
}
Import it
import VuexPersistence from 'vuex-persist'
NOTE: In browsers, you can directly use
window.VuexPersistence
Create an object
const vuexLocal = new VuexPersistence({
storage: window.localStorage
})
// or in Typescript
const vuexLocal = new VuexPersistence<RootState>({
storage: window.localStorage
})
Use it as Vue plugin. (in typescript)
const store = new Vuex.Store<State>({
state: { ... },
mutations: { ... },
actions: { ... },
plugins: [vuexLocal.plugin]
})
(or in Javascript)
const store = {
state: { ... },
mutations: { ... },
actions: { ... },
plugins: [vuexLocal.plugin]
}
When creating the VuexPersistence object, we pass an options object
of type PersistOptions.
Here are the properties, and what they mean -
| Property | Type | Description |
|---|---|---|
| key | string | The key to store the state in the storage |
Default: 'vuex' | | storage | Storage (Web API) | localStorage, sessionStorage, localforage or your custom Storage object.
Must implement getItem, setItem, clear etc.
Default: window.localStorage | | saveState | function
(key, state[, storage]) | If not using storage, this custom function handles
saving state to persistence | | restoreState | function
(key[, storage]) => state | If not using storage, this custom function handles
retrieving state from storage | | reducer | function
(state) => object | State reducer. reduces state to only those values you want to save.
By default, saves entire state | | filter | function
(mutation) => boolean | Mutation filter. Look at mutation.type and return true
for only those ones which you want a persistence write to be triggered for.
Default returns true for all mutations | | modules | string[] | List of modules you want to persist. (Do not write your own reducer if you want to use this) | | asyncStorage | boolean | Denotes if the store uses Promises (like localforage) or not (you must set this to true when suing something like localforage)
Default: false | | supportCircular | boolean | Denotes if the state has any circular references to itself (state.x === state)
Default: false |
Your reducer should not change the shape of the state.
const persist = new VuexPersistence({
reducer: (state) => state.products,
...
})
Above code is wrong You intend to do this instead
const persist = new VuexPersistence({
reducer: (state) => ({products: state.products}),
...
})
If you have circular structures in your state
let x = { a: 10 }
x.x = x
x.x === x.x.x // true
x.x.x.a === x.x.x.x.a //true
JSON.parse() and JSON.stringify() will not work.
You'll need to install flatted
npm install flatted
And when constructing the store, add supportCircular flag
new VuexPersistence({
supportCircular: true,
...
})
Quick example -
import Vue from 'vue'
import Vuex from 'vuex'
import VuexPersistence from 'vuex-persist'
Vue.use(Vuex)
const store = new Vuex.Store<State>({
state: {
user: { name: 'Arnav' },
navigation: { path: '/home' }
},
plugins: [new VuexPersistence().plugin]
})
export default store
Here is an example store that has 2 modules, user and navigation
We are going to save user details into a Cookie (using js-cookie)
And, we will save the navigation state into localStorage whenever
a new item is added to nav items.
So you can use multiple VuexPersistence instances to store different
parts of your Vuex store into different storage providers.
Warning: when working with modules these should be registered in
the Vuex constructor. When using store.registerModule you risk the
(restored) persisted state being overwritten with the default state
defined in the module itself.
import Vue from 'vue'
import Vuex, { Payload, Store } from 'vuex'
import VuexPersistence from 'vuex-persist'
import Cookies from 'js-cookie'
import { module as userModule, UserState } from './user'
import navModule, { NavigationState } from './navigation'
export interface State {
user: UserState
navigation: NavigationState
}
Vue.use(Vuex)
const vuexCookie = new VuexPersistence<State, Payload>({
restoreState: (key, storage) => Cookies.getJSON(key),
saveState: (key, state, storage) =>
Cookies.set(key, state, {
expires: 3
}),
modules: ['user'], //only save user module
filter: (mutation) => mutation.type == 'logIn' || mutation.type == 'logOut'
})
const vuexLocal = new VuexPersistence<State, Payload>({
storage: window.localStorage,
reducer: (state) => ({ navigation: state.navigation }), //only save navigation module
filter: (mutation) => mutation.type == 'addNavItem'
})
const store = new Vuex.Store<State>({
modules: {
user: userModule,
navigation: navModule
},
plugins: [vuexCookie.plugin, vuexLocal.plugin]
})
export default store
This now supports Vuex strict mode
(Keep in mind, NOT to use strict mode in production)
In strict mode, we cannot use store.replaceState so instead we use a mutation
You'll need to keep in mind to add the RESTORE_MUTATION to your mutations
See example below
To configure with strict mode support -
import Vue from 'vue'
import Vuex, { Payload, Store } from 'vuex'
import VuexPersistence from 'vuex-persist'
const vuexPersist = new VuexPersistence<any, any>({
strictMode: true, // This **MUST** be set to true
storage: localStorage,
reducer: (state) => ({ dog: state.dog }),
filter: (mutation) => mutation.type === 'dogBark'
})
const store = new Vuex.Store<State>({
strict: true, // This makes the Vuex store strict
state: {
user: {
name: 'Arnav'
},
foo: {
bar: 'baz'
}
},
mutations: {
RESTORE_MUTATION: vuexPersist.RESTORE_MUTATION // this mutation **MUST** be named "RESTORE_MUTATION"
},
plugins: [vuexPersist.plugin]
})
Some of the most popular ways to persist your store would be -
There is Window.Storage API as defined by HTML5 DOM specs, which implements the following -
```typescript interface Storage { readonly length: number clear(): void getItem(key: string): string | null key(index: number): string | null removeItem(key: string): void setItem(key: string, data: string):
$ claude mcp add vuex-persist \
-- python -m otcore.mcp_server <graph>