Replies: 3 comments 1 reply
-
zustand runs a migration anytime there is a version mismatch between the version in const store = createStore(
persist(() => ({}), {
name: 'storage-key',
version: 1,
migrate(prevState, prevVersion) {
console.log({ prevState, prevVersion })
// 1st time: doesn't run
// 2nd time: { prevState: {}, prevVersion: 0 }
return { foo: 'bar' }
},
})
)
console.log(localStorage.getItem('storage-key'))
// 1st time: {"state":{},"version":0}
// 2nd time: {"state":{"foo":"bar"},"version":1} If you found my answer satisfactory, please consider supporting me. Even a small amount is greatly appreciated. Thanks friend! 🙏 |
Beta Was this translation helpful? Give feedback.
-
This question is quite old now but for anyone stumbling upon it I am not sure the answer given above fully answers the question (with the latest version of Zustand at least). The It would be useful IMO to be able to perform an "empty" migration, but a workaround is possible using
|
Beta Was this translation helpful? Give feedback.
-
I tried out both solution above but was not able to find a way to force the migrate function to run on initial persist, until I read the source code of the
@atothewest is correct here that the migration will be skipped if the storage is empty since the migration will only run if the previous A workaround to always force migration to run on initial persist would be to return To make it simpler, I have created a decorator below that can be used as a workaround to run the migration on first persist: import { create } from 'zustand';
import { createJSONStorage, persist, PersistStorage, type StateStorage, StorageValue } from 'zustand/middleware';
export function forceMigrationOnInitialPersist<S>(originalStorage: PersistStorage<S> | undefined): PersistStorage<S> | undefined {
try {
if (!originalStorage) {
return undefined;
}
const modifiedStorage: PersistStorage<S> = {
getItem: async name => {
const item = await originalStorage.getItem(name);
if (item) {
return item;
}
return {
state: undefined,
version: 0
} as StorageValue<S>;
},
setItem: originalStorage.setItem,
removeItem: originalStorage.removeItem
};
return modifiedStorage;
} catch (e) {
console.error('forceMigrationOnInitialPersist', e);
return undefined;
}
}
export const useAuthStore = create(
persist(
() => ({
foo: 'bar',
}),
{
name: 'auth-storage',
storage: forceMigrationOnInitialPersist(createJSONStorage(() => localStorage)),
version: 1,
migrate: async (state, version) => {
if (version === 0) {
// run your initial/forced migration here! it supports async, so you can read IndexedDB or anything similar here
// the state would be the default state here, in ths case: { foo: 'bar' }
}
return state;
}
}
)
); |
Beta Was this translation helpful? Give feedback.
-
version: 1
and thenmigrate
function to have v1 do a migration from AsyncStorage to zustand.I can't find a good way to do this. zustand state goes to v1 directly with no migration, since there is no persisted state already in v0.
any way I could do that better? or a way to force zustand to run the migration?
Thanks.
Beta Was this translation helpful? Give feedback.
All reactions