feat: add keepPreviousData option to eliminate UI flash during transitions#68
Open
renchris wants to merge 7 commits intorocicorp:mainfrom
Open
feat: add keepPreviousData option to eliminate UI flash during transitions#68renchris wants to merge 7 commits intorocicorp:mainfrom
renchris wants to merge 7 commits intorocicorp:mainfrom
Conversation
- Add keepPreviousData option (default: true) to useSubscribe - Preserve previous snapshot during dependency transitions - Eliminates UI flash when switching between subscriptions - Bump version to 6.1.0
Safety improvements: - Add generation counter to prevent race conditions with stale subscriptions - Add isMounted guard to prevent setState after unmount - Detect transitions during render for immediate default when keepPreviousData=false - Clear prevSnapshotRef in cleanup when keepPreviousData is false - Capture current snapshot when deps change (shows most recent data, not oldest) New tests: - Explicit keepPreviousData: true/false behavior tests - Rapid dependency changes (A → B → C) race condition test - Previous data was null test - Multiple transitions (A → B → A → null → B) test - Generation counter ignores stale data test Documentation: - Comprehensive JSDoc for useSubscribe, Subscribable, UseSubscribeOptions - Updated README with React 19+ fork section and keepPreviousData feature docs - Fixed RemoveUndefined type to use Exclude<T, undefined>
- Fix memory leak: always clear prevSnapshotRef on unmount - Fix unsafe spread: use (dependencies ?? []) for null safety - Fix edge case: add hasRunEffectRef to properly detect initial mount vs transitions (r=undefined at start is now handled correctly) - Add try-catch in doCallback: isolate errors so one bad callback doesn't block others - Improve types: use ReadonlyArray<unknown> for prevDepsRef
Contributor
|
Thanks. This makes sense to me. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
keepPreviousDataoption (default:true) touseSubscribethat preserves previous subscription data during dependency transitions, eliminating the UI flash that occurs when switching between subscriptions.Problem
When
useSubscribedependencies change (e.g., navigating/list/AAA→/list/BBB), users experience a brief flash where the default value is shown before new data arrives:History
setSnapshot(def)setSnapshot(undefined)unstable_batchedUpdatesThe flash was introduced in v4.0.0 (PR #57) as a side effect of type safety improvements, not as an intentional UX decision.
Solution
Behavior:
keepPreviousData: true(default): Previous data stays visible until new subscription fireskeepPreviousData: false: Immediately shows default value (v4.0.0+ behavior)Implementation Details
prevSnapshotRef: Tracks the most recent successful subscription dataisMountedguard: Prevents setState after component unmounthasRunEffectRef: Distinguishes initial mount from dependency transitionsBreaking Change
This changes the default behavior from v4.0.0+. Users who relied on seeing the default value during transitions can opt-out:
Why Default to
truekeepPreviousDatafor UXTest Coverage
keepPreviousData: truepreserves data across transitionskeepPreviousData: falseresets to defaultRelated
Partially addresses #19 (Support suspense in useSubscribe) by eliminating the primary use case for Suspense—avoiding flash during transitions—without requiring Suspense boundaries.
Published as
@renchris/replicache-react@6.1.0for testing.