Skip to content

fix(persist): clearStorage() should invalidate concurrent async rehydration - #3555

Merged
dai-shi merged 4 commits into
mainfrom
copilot/fix-issue-with-selectors
Aug 12, 2026
Merged

fix(persist): clearStorage() should invalidate concurrent async rehydration#3555
dai-shi merged 4 commits into
mainfrom
copilot/fix-issue-with-selectors

Conversation

Copilot AI commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

With async storage, clearStorage() can race with a pending rehydrate(): the item is removed, but the older async read completes afterward and writes the cleared value back into state.

rehydrate() already uses hydrationVersion to discard stale concurrent hydrations — clearStorage() simply wasn't advancing that counter.

Summary

  • src/middleware/persist.ts: Increment hydrationVersion at the start of clearStorage(). Any in-flight rehydrate() then fails the existing currentVersion !== hydrationVersion staleness checks and exits without applying state.

  • tests/persistAsync.test.tsx: Five new tests covering:

    • Stale async getItem result discarded after clearStorage()
    • Stale async migrate result discarded after clearStorage()
    • Hydration still invalidated when removeItem throws
    • clearStorage() after a completed hydration does not reset live state
    • onRehydrateStorage/onFinishHydration callbacks suppressed for stale hydration; subsequent rehydrate() works correctly

Close #3554

…le async hydration

Addresses #3554

When clearStorage() is called while an async rehydrate() is still pending,
the storage item gets removed but the older read can finish afterward and
apply the value that was just cleared.

Fix: increment hydrationVersion in clearStorage() so any in-flight hydration
is treated as stale and discarded, consistent with how concurrent rehydrate()
calls are already handled.

Co-authored-by: dai-shi <490574+dai-shi@users.noreply.github.com>
@vercel

vercel Bot commented Aug 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
zustand-demo Ready Ready Preview Aug 12, 2026 11:24pm

Request Review

@dai-shi
dai-shi marked this pull request as ready for review August 10, 2026 14:39
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

Size Change: +6 B (+0.05%)

Total Size: 13.2 kB

📦 View Changed
Filename Size Change
dist/esm/middleware.mjs 4.11 kB +3 B (+0.07%)
dist/middleware.js 4.12 kB +3 B (+0.07%)
ℹ️ View Unchanged
Filename Size
dist/esm/index.mjs 64 B
dist/esm/middleware/immer.mjs 212 B
dist/esm/react.mjs 342 B
dist/esm/react/shallow.mjs 198 B
dist/esm/shallow.mjs 82 B
dist/esm/traditional.mjs 412 B
dist/esm/vanilla.mjs 405 B
dist/esm/vanilla/shallow.mjs 557 B
dist/index.js 244 B
dist/middleware/immer.js 231 B
dist/react.js 357 B
dist/react/shallow.js 213 B
dist/shallow.js 189 B
dist/traditional.js 426 B
dist/vanilla.js 418 B
dist/vanilla/shallow.js 568 B

compressed-size-action

@pkg-pr-new

pkg-pr-new Bot commented Aug 10, 2026

Copy link
Copy Markdown

commit: f7e54de

Co-authored-by: dai-shi <490574+dai-shi@users.noreply.github.com>
Co-authored-by: dai-shi <490574+dai-shi@users.noreply.github.com>
@dai-shi
dai-shi merged commit 3febf8c into main Aug 12, 2026
32 checks passed
@dai-shi
dai-shi deleted the copilot/fix-issue-with-selectors branch August 12, 2026 23:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants