Persist VueJs Pinia state data in sessionStorage or other storages, heavilly influenced by vuex-persistedstate.
Documentation: HERE
Persist pinia state data in sessionStorage or other storages.
Home Page: https://Seb-L.github.io/pinia-plugin-persist/
License: MIT License
Persist VueJs Pinia state data in sessionStorage or other storages, heavilly influenced by vuex-persistedstate.
Documentation: HERE
app.js
`import { defineStore } from 'pinia'
import { ref, reactive } from 'vue'
export const useAppStore = defineStore('app', () => {
// state
const isCollapse = ref(false)
// actions
function setIsCollapse(isCollapse) {
this.isCollapse = isCollapse
}
return {
isCollapse
setIsCollapse
}
}, {
persist: {
enabled: true,
strategies: [
{
key: 'appStore',
storage: localStorage
},
]
}
})
`
isCollapse default value is false,in the page ,I clicked a button change value to true
In localStorage ,have object
{
isCollapse: true
}
then I refresh this page , isCollapse 's value should be true
but actually , the value is false
so I think is $patch had no effect?
issue
nuxt/nuxt#23163
related revision details
nuxt/nuxt#23148
The custom storage is a Object parameter of pinia-plugin-persist
// this will blow up in nuxt SSR because it is not in a component.
const token = useCookie<string>('userToken', rawEncode)
const cookiesStorage = {
setItem (_key: string, state: string) {
try {
token.value = JSON.parse(state).userToken
} catch (err) {
return undefined
}
},
getItem (_key: string) {
try {
return JSON.stringify({ userToken: token.value })
} catch (err) {
return undefined
}
}
}
const useStore = defineStore({
// ...
persist: {
enabled: true,
strategies: [
{
storage: cookiesStorage,
paths: ['accessToken']
},
],
}
}
It runs before
the useStore
.
But this is problematic when using with SSR frameworks.
Because SSR frameworks (such as nuxt) relies on useSSRContext
to retrieve of information about current request.
Which isn't available outside of component life cycle.
My current hack about this is
const useStore = defineStore({
// ...
strategies: [
{
get storage () { return getCookiesStorage() as unknown as Storage },
paths: ['userToken']
}
]
// ...
})
To delay the deference of getCookiesStorage and prevent it from crash the server.
But that isn't a proper usage at all.
I think this should be changed to (or as an alternative option) a factory function that called during useStore, so it don't cause probelm.
It works totally fine when there was only ONE pinia store in my application. After I added another pinia definition and it just went weird. It seems that there could be ONLY ONE store that can be persisted into the storage at a time, while others just freeze in the storage, no matter when any actions or $reset being called.
And pinia works fine, though. Just the persistence goes wrong.
// authStore.js
const useAuthStore = defineStore("auth", { ... })
// routerStore.js
const useRouterStore = defineStore("router", { ... })
Here are the dependencies in my package.json:
"dependencies": {
// ......
"pinia": "^2.0.0-rc.10",
"pinia-plugin-persist": "^1.0.0",
"vue": "^3.2.25",
}
I have a project with Vue 2.7 and this plugin is not working. You can see a (non)working reproduction in here https://github.com/Elucid-Social/test-vue-apollo-cache/pull/1/files
The only difference is that now with Pinia we need to use VuePiniaPlugin
import { createPinia, PiniaVuePlugin } from 'pinia'
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
Hey there,
I followed the integration instructions in the documentation and am receiving an error.
I've created a reproduction here: https://github.com/hex-digital/nuxt-2/tree/pinia-persist and a PR to see it more easily here (hex-digital/nuxt-2#1)
It's set up by:
yarn create nuxt-app fresh-nuxt
yarn add -D pinia @pinia/nuxt @nuxtjs/composition-api pinia-plugin-persist
buildModules: [
'@nuxtjs/composition-api/module',
'@pinia/nuxt',
'pinia-plugin-persist/nuxt',
];
yarn dev
❯ yarn dev
yarn run v1.22.17
$ nuxt
FATAL Package subpath './nuxt' is not defined by "exports" in /Users/jamie/Sites/bignight/fresh-nuxt/node_modules/pinia-plugin-persist/package.json
at new NodeError (node:internal/errors:371:5)
at throwExportsNotFound (node:internal/modules/esm/resolve:440:9)
at packageExportsResolve (node:internal/modules/esm/resolve:692:3)
at resolveExports (node:internal/modules/cjs/loader:482:36)
at Function.Module._findPath (node:internal/modules/cjs/loader:522:31)
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27)
at Function.resolve (node:internal/modules/cjs/helpers:108:19)
at p (node_modules/jiti/dist/jiti.js:1:52925)
at Resolver.g [as _require] (node_modules/jiti/dist/jiti.js:1:54200)
at Resolver.requireModule (node_modules/@nuxt/core/dist/core.js:381:29)
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ │
1 export default {
│ ✖ Nuxt Fatal Error │
│ │
│ Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './nuxt' is not defined by "exports" in │
│ /Users/jamie/Sites/bignight/fresh-nuxt/node_modules/pinia-plugin-persist/package.json │
│ │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Note that for Nuxt, the Pinia docs say to add @pinia/nuxt
to buildModules
, but this plugins docs say to add pinia/nuxt
. Adding pinia/nuxt
as you suggest gives a similar error relating to pinia.
It's unsupported in vue2.x ,right?
vue3 not support?
I use the same code to find that what works in JS projects doesn't work well in TS projects .
Successful build.
The following error is shown:
node_modules/pinia-plugin-persist/dist/index.d.ts:1:21 - error TS2724: '"pinia"' has no exported member named 'GettersTree'. Did you mean '_GettersTree'?
1 import { StateTree, GettersTree, PiniaPluginContext } from 'pinia';
Thank you for the plugin!
Refresh page localstorage no longer changes
I created a new vue-ts project using pnpm create vite@latest my-app --template vue-ts
, then I add pinia
& pinia-plugin-persist
deps。I set up typescript config by the doc, when i import pinia-plugin-persist
, vscode will raise an error:
Could not find a delaration file for module pinia-plugin-persist.
There are types at '/xxx/my-app/node_modules/.pnpm/pinia-plugin-persist/dist/index.d.ts', but this result could not be resolved when respectiong package.json "exports". The 'pinia-plugin-persist' library may need to update its package.json or typings.
Here is my tsconfig.json
file:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"types": ["pinia-plugin-persist"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
To fix this bug, I have to change the config:
-- "moduleResolution": "bundler",
++ "moduleResolution": "node",
Please support typescript 5.0+!
May be this link clarifies the problem more clean: Add the types condition to the package.json#exports
tip:
However, directly enter the login (http://localhost:3000/login), enter the email address and name, click login, and
enter the home page. At this time, clicking refresh will not lose user information.
when i try used nuxtjs3 vue3 typescript
this error display "sessionStorage is not defined"
There is no problem when using the Basic Usage method.
When using separate storage(localStorage, sessionStorage) for strategies in Advanced Usage
I get an 'is not defined' error.
Do I need any special settings?
I've created a PR for this already, as it's a simple one-line and non-interfering fix, merci :)
It's here, just to save the moment. It's tested via yalc.
My case involves an import() promise, but the definition still needs to be there in the npm package.
Is there any intent to be able to support an async storage provider like localforage?
import localforage from 'localforage'
export default {
setItem: async (key, value) => {
return localforage.setItem(key, value)
},
getItem: async (key) => {
return localforage.getItem(key)
}
}
I did try the above without any success.
Hi,
How can this plugin be implemented in a Nuxt 3 project? and also what would be the way to use local Storage and cookies, or just localStorage?
Would it be possible to add this to the documentation?
Thanks
I tried to use it in Vue3 with typescript, but this warning appears... any hints?
It is supported if you use vue-composition-api, like here: https://seb-l.github.io/pinia-plugin-persist/#vue2
it get wrong if this store add attribute 'persist'!
"Error: [vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function."
Originally posted by @benweng in #27 (comment)
I'm using Vue 2.7 + Nuxt 2.16 + @nuxtjs/composition API
export const useDictionaryStore = defineStore(
'dictionary',
() => {
// ...code removed
return {
someData,
}
},
{
persist: {
enabled: true,
strategies: [
{
storage: localStorage,
},
],
},
}
)
Getting TS error: Argument of type '{ persist: { enabled: boolean; strategies: { storage: Storage; }[]; }; }' is not assignable to parameter of type 'DefineSetupStoreOptions<"dictionary", _UnwrapAll
Even though i've added types in tsconfig.json
How do I persist the state of a store if the initial default state has not changed? If the defaults are accepted, I don't need to ask for the user's preferences for another 365 days. But I must get the user to accept the defaults before using them.
I am creating a store that starts with everything given a default value. If a user changes any default values, it saves the store to a cookie. However, if the user accepts the default values without changing anything and presses an 'agree' button, the store’s state does not get saved into a cookie. No cookie is created.
I looked at the source and found updateStorage
and wondered if that could be used in my component’s agree
method. However, updateStorage
expects a strategy as its first argument, but I don’t necessarily know the strategy inside a component, and a store could have more than one.
The docs have instruction for how to use this plugin with Vue 2 and Nuxt but nothing for Vue 3.
Thanks for writing this plugin.
import { watch } from '@vue/composition-api';
change to:
import { watch } from '@vue/runtime-core';
runtime no error
but not work
how add pinia-plugin-persist to vite-plugin-ssr plugin? it gives this error 'sessionStorage is not defined'
Just a heads up... installing this package contains only these files:
There is not any source files
默认情况下,state subscriptions 绑定到添加它们的组件(如果 store 位于组件的 setup() 中)。 意思是,当组件被卸载时,它们将被自动删除。 如果要在卸载组件后保留它们,请将 { detached: true } 作为第二个参数传递给 detach 当前组件的 state subscription
see here
store.$subscribe(() => {
strategies.forEach((strategy) => {
updateStorage(strategy, store);
});
},{ detached: true });
vue3 ssr
add "pinia-plugin-persist"
npm run build
run worry
/src/node_modules/pinia-plugin-persist/dist/pinia-persist.es.js:38
export { index as default, updateStorage };
^^^^^^
SyntaxError: Unexpected token 'export'
at internalCompileFunction (node:internal/vm:73:18)
at wrapSafe (node:internal/modules/cjs/loader:1178:20)
at Module._compile (node:internal/modules/cjs/loader:1220:27)
at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
at Module.load (node:internal/modules/cjs/loader:1119:32)
at Module._load (node:internal/modules/cjs/loader:960:12)
at ModuleWrap. (node:internal/modules/esm/translators:169:29)
at ModuleJob.run (node:internal/modules/esm/module_job:194:25)
package.json
add type=module
I'm currently working on getting a minimum reproducible example for this problem but long story short it seems to be that if:
Only 1 type of storage will be initialised and only one store will have it's data available there.
Will update the issue with more info and possibly a PR as I go.
Storage update is already done by the helper function.
https://github.com/Seb-L/pinia-plugin-persist/blob/main/src/index.ts#L49
environment
Problem statement
When using pina persistence, if an array is stored and the field in the array object is underlined, the plug-in will change it to camel case.
import { defineStore } from "pinia"
export const useItemStore = defineStore({
id: 'useItemStore',
state: () => {
return {
rowItem: {
}
}
},
getters: {
getCurItem(state) {
return state.rowItem
}
},
actions: {
setMenuItem(val: any) {
this.rowItem = val
},
resetData() {
this.rowItem = {}
}
},
persist: {
enabled: true,
strategies: [
{
key: 'useItemStore',
storage: sessionStorage
}
]
}
})
const data = [
{
"id": "653773c022bd673a6b02dd88",
"admin_id": "JSZH00005",
"name": "root",
"email": "[email protected]",
"phone": "13800000000",
"role_id": "6537739b339a3a4728017968",
"role_name": "amin",
"status": 1,
"node_id": null,
"created_at": "2023-10-24 07:35:29",
"updated_at": "2024-04-10 11:40:16"
},
{
"id": "64b89e21050ca676f20c191b",
"admin_id": "JSZH00004",
"name": "dev",
"email": "[email protected]",
"phone": "15088888888",
"role_id": "64b89defd7098d53b00a18f6",
"role_name": "dev",
"status": 1,
"node_id": "123",
"created_at": "2023-07-20 02:38:25",
"updated_at": "2024-04-10 11:08:05"
},
{
"id": "64b0bac0e966e166d9093d23",
"admin_id": "JSZH00001",
"name": "admin",
"email": "[email protected]",
"phone": "18688889999",
"role_id": "64b0bac0e966e166d9093d22",
"role_name": "superadmin",
"status": 1,
"node_id": "Ziz78vM5cAxBayywmAMnXFpLWe21UpeA5i",
"created_at": "2023-07-14 03:02:24",
"updated_at": "2024-04-10 11:53:19"
}
]
//use
itemStore.setMenuItem(data)
2.The last underscored field in the array will not be changed to camelCase, and the other fields will be created with CamelCase.
It can be seen that as long as it is not the last item in the array, underlined camel case data will be created.
So i am having an issue when user login store is set with user data and all for first time it store it in localstorage or sessionstorage, when the user logouts the storage clear function will be called. after if i try to login with out refreshing the page presist doesn't work.
***note even when login in the second time pinia get populated with data
Thank you for a great plugin.
May I suggest to adapt the docs according to a bug I had last night?
I write my vues, including the pinia stores along the script setup
syntax
So, I was struggling a few hours on a
'set' on proxy: trap returned falsish for property
bug
The property that lifted the error was a getter (computed, read-only).
Using
{
persist: {
enabled: true
}
}
will persist all the variables, including the getters.
Navigating from page to page or refreshing a page will try to set a getter though a getter is read-only.
Solution:
you must use strategies and restrict the variables that are persisted with path (and avoid having a getter in the path)
{
persist: {
enabled: true,
strategies: {
path: ['state_variable_1', 'state_variable_2', '...] // avoid getter in the list
}
}
}
I tried the installation for Nuxt in my Nuxt 3 project (RC 6) but it didn't work. I propose #49 to complete the documentation.
'"pinia"' has no exported member named 'GettersTree'. Did you mean '_GettersTree'? 1 import { StateTree, GettersTree, PiniaPluginContext } from 'pinia';
could set a dynamic custom storage key ? like user store id state
It is suggested to add a new feature to enable cross-page state synchronization in Pinia Plugin Persist. This feature can work with listening to the localStorage event, which will automatically synchronize the status of other web pages after one page updates the status. This will make it easier to handle most complex synchronization logic.
useEventListener(window, 'storage', (event) => {
if (event.key === STORAGE_KEY) {
const obj = JSON.parse(event.newValue || '{}')
mykey.value = obj.mykey
}
})
默认情况下,state subscriptions 绑定到添加它们的组件(如果 store 位于组件的 setup() 中)。 意思是,当组件被卸载时,它们将被自动删除。 如果要在卸载组件后保留它们,请将 { detached: true } 作为第二个参数传递给 detach 当前组件的 state subscription
see here
store.$subscribe(() => {
strategies.forEach((strategy) => {
updateStorage(strategy, store);
});
},{ detached: true });
Just wondering, there is another solution now, but still i think yours is pretty simple and easy to use
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.