Skip to content

Draft: Add event.persisted check in restore handler to prevent unnecessary rehydration on page load#66

Closed
d8corp wants to merge 6 commits intonanostores:mainfrom
d8corp:fix_first-init-bug
Closed

Draft: Add event.persisted check in restore handler to prevent unnecessary rehydration on page load#66
d8corp wants to merge 6 commits intonanostores:mainfrom
d8corp:fix_first-init-bug

Conversation

@d8corp
Copy link
Copy Markdown
Contributor

@d8corp d8corp commented Feb 4, 2026

📌 Summary

This PR enhances the reliability of the persistentAtom store hydration logic by introducing a check for event.persisted in the pageshow event handler (restore function). This ensures that state is only restored from persistent storage when the page is being restored from the bfcache (back-forward cache), and not on the initial page load — where the store is already correctly initialized from localStorage.

🔍 Problem

Previously, the restore function was called on every pageshow event — including the initial page load. This caused redundant and potentially conflicting rehydration of the store from localStorage.

✅ Solution

Added this guard clause in the restore function:

if (!event.persisted) return

This ensures that state restoration only occurs when:

  • The page is being restored from the browser’s bfcache (e.g., after navigating back/forward)
  • The page was not freshly loaded

This matches the intended behavior of persistent storage: recover state after a cached navigation, not reapply it on every load.

💡 Why This Matters

  • Performance: Avoids redundant JSON parsing and state updates.
  • User Experience: Prevents UI flickering or state resets on page load.
  • Correctness: Aligns with browser semantics — pageshow.persisted === true is the standard way to detect bfcache restoration.

🛠 Changes

  • ✅ Added if (e && !e.persisted) return to restore function in persistentAtom
  • ✅ No breaking changes — behavior is more correct, not different in normal cases
  • ✅ All tests and utilities (useTestStorageEngine, etc.) remain unchanged and compatible

📚 Background


📌 Recommendation

This is a bug fix and performance improvement, not a feature. It makes the library behave more predictably in modern browsers with bfcache enabled (which is now the default in Chrome, Firefox, and Safari).

Merge this to improve user experience and eliminate edge-case bugs.

@d8corp d8corp changed the title Add event.persisted check in restore handler to prevent unnecessary rehydration on page load Draft: Add event.persisted check in restore handler to prevent unnecessary rehydration on page load Feb 4, 2026
@ai
Copy link
Copy Markdown
Member

ai commented Feb 4, 2026

Removed redundant restore() call from onMount (it was triggering hydration on load, conflicting with initial store value)

I afraid of this change.

If I create a store, it will not subscribe to localStorage changes. It will subscribe only on mount (first listener).

So we could have error here:

  1. Open app in browser tab 1. settings store loaded value from localStorage .
  2. Open the same app in tab 2. settings store loaded value from localStorage .
  3. Call settings.listen() in tab 2. It subscribes to the localStorage updates.
  4. Change store in tab 2: settings.set(newSettings)
  5. Call settings.listen() in tab 1. It subscribes to the localStorage updates. But the value in settings store will be old.

@d8corp
Copy link
Copy Markdown
Contributor Author

d8corp commented Feb 4, 2026

@ai, please review these changes.

Should we keep the dist folder in the repo?

Our .gitignore currently excludes test/demo/dist/, so we need to decide: remove the ignore rule, delete the folder from the repo, or keep it for a reason?

I also added:

  • A couple of npm scripts to package.json—they help verify the build bundle and prevent WebSocket errors in bfcache.
  • Tests that check the number of decode function calls.

@d8corp
Copy link
Copy Markdown
Contributor Author

d8corp commented Feb 5, 2026

@ai I added an additional PR that depends on this one.

@d8corp d8corp marked this pull request as draft February 5, 2026 11:07
@ai ai closed this Feb 5, 2026
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