Skip to content

Commit dad3641

Browse files
fix(storage): avoid calling setItem with the state just retrieved (#2678)
1 parent a56e76d commit dad3641

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

src/middleware/persist.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -459,27 +459,34 @@ const newImpl: PersistImpl = (config, baseOptions) => (set, get, api) => {
459459
deserializedStorageValue.version !== options.version
460460
) {
461461
if (options.migrate) {
462-
return options.migrate(
463-
deserializedStorageValue.state,
464-
deserializedStorageValue.version,
465-
)
462+
return [
463+
true,
464+
options.migrate(
465+
deserializedStorageValue.state,
466+
deserializedStorageValue.version,
467+
),
468+
] as const
466469
}
467470
console.error(
468471
`State loaded from storage couldn't be migrated since no migrate function was provided`,
469472
)
470473
} else {
471-
return deserializedStorageValue.state
474+
return [false, deserializedStorageValue.state] as const
472475
}
473476
}
477+
return [false, undefined] as const
474478
})
475-
.then((migratedState) => {
479+
.then((migrationResult) => {
480+
const [migrated, migratedState] = migrationResult
476481
stateFromStorage = options.merge(
477482
migratedState as S,
478483
get() ?? configResult,
479484
)
480485

481486
set(stateFromStorage as S, true)
482-
return setItem()
487+
if (migrated) {
488+
return setItem()
489+
}
483490
})
484491
.then(() => {
485492
// TODO: In the asynchronous case, it's possible that the state has changed

tests/persistSync.test.tsx

+22
Original file line numberDiff line numberDiff line change
@@ -738,4 +738,26 @@ describe('persist middleware with sync configuration', () => {
738738
undefined,
739739
)
740740
})
741+
742+
it('does not call setItem when hydrating from its own storage', async () => {
743+
const setItem = vi.fn()
744+
const storage = {
745+
getItem: (name: string) => ({
746+
state: { count: 42, name },
747+
version: 0,
748+
}),
749+
setItem,
750+
removeItem: () => {},
751+
}
752+
753+
const useBoundStore = create(
754+
persist(() => ({}), {
755+
name: 'test-storage',
756+
storage: storage,
757+
}),
758+
)
759+
760+
expect(useBoundStore.persist.hasHydrated()).toBe(true)
761+
expect(setItem).toBeCalledTimes(0)
762+
})
741763
})

0 commit comments

Comments
 (0)