-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
feat(persistQueryClient): PersistQueryClientProvider #3248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 14 commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
5a0aab7
feat(persistQueryClient): PersistQueryClientProvider
TkDodo 5c4de91
feat(persistQueryClient): PersistQueryClientProvider
TkDodo 985c564
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo 00d0ad4
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo 261777c
feat(persistQueryClient): PersistQueryClientProvider
TkDodo 0f6de7a
feat(persistQueryClient): PersistQueryClientProvider
TkDodo 2d410fb
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo 363e3f7
feat(persistQueryClient): PersistQueryClientProvider
TkDodo 459ac56
feat(persistQueryClient): PersistQueryClientProvider
TkDodo b301ce2
feat(persistQueryClient): PersistQueryClientProvider
TkDodo 82ed46d
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo c86607f
feat(persistQueryClient): PersistQueryClientProvider
TkDodo da52e82
feat(persistQueryClient): PersistQueryClientProvider
TkDodo 00a6bcd
feat(persistQueryClient): PersistQueryClientProvider
TkDodo 90ce9ff
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo 2c21e75
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo 74f9748
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo 6bef21c
Merge branch 'alpha' into feature/persistQueryClient
TkDodo fc00442
make restore in mockPersister a bit slower to stabilize tests
TkDodo 7befff0
Merge branch 'alpha' into feature/persistQueryClient
TkDodo 9b05e02
Merge branch 'alpha' into feature/persistQueryClient
TkDodo 879495a
better persistQueryClient docs
TkDodo c6565db
Merge branch 'alpha' into feature/persistQueryClient
TkDodo 507edca
feat(PersistQueryClientProvider): make sure we can hydrate into multi…
TkDodo 8f9c746
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo 702159f
offline example
TkDodo 4146a69
extract to custom hook
TkDodo 291b0a5
Merge remote-tracking branch 'react-query/alpha' into feature/persist…
TkDodo e78a470
remove onError callback
TkDodo 91e2afb
just ignore stale hydrations if the client changes
TkDodo 29d52f8
Revert "just ignore stale hydrations if the client changes"
TkDodo 433fd8a
just ignore stale hydrations if the client changes
TkDodo 2570c8a
Merge remote-tracking branch 'tannerlinsley/alpha' into feature/persi…
TkDodo b2cd6b0
since QueryClientProviderProps is now a union type, we can't extend i…
TkDodo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import React from 'react' | ||
|
|
||
| import { persistQueryClient, PersistQueryClientOptions } from './persist' | ||
| import { QueryClientProvider, QueryClientProviderProps } from '../reactjs' | ||
| import { IsHydratingProvider } from '../reactjs/Hydrate' | ||
|
|
||
| export interface PersistQueryClientProviderProps | ||
| extends QueryClientProviderProps { | ||
| persistOptions: Omit<PersistQueryClientOptions, 'queryClient'> | ||
| onSuccess?: () => void | ||
| } | ||
|
|
||
| export const PersistQueryClientProvider = ({ | ||
| client, | ||
| children, | ||
| persistOptions, | ||
| onSuccess, | ||
| ...props | ||
| }: PersistQueryClientProviderProps): JSX.Element => { | ||
| const [isHydrating, setIsHydrating] = React.useState(true) | ||
| const refs = React.useRef({ persistOptions, onSuccess }) | ||
|
|
||
| React.useEffect(() => { | ||
| refs.current = { persistOptions, onSuccess } | ||
| }) | ||
|
|
||
| React.useEffect(() => { | ||
| const [unsubscribe, promise] = persistQueryClient({ | ||
| ...refs.current.persistOptions, | ||
| queryClient: client, | ||
| }) | ||
|
|
||
| promise.then(() => { | ||
| refs.current.onSuccess?.() | ||
| setIsHydrating(false) | ||
| }) | ||
|
|
||
| return unsubscribe | ||
Ephem marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }, [client]) | ||
|
|
||
| return ( | ||
| <QueryClientProvider client={client} {...props}> | ||
| <IsHydratingProvider value={isHydrating}>{children}</IsHydratingProvider> | ||
TkDodo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </QueryClientProvider> | ||
| ) | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,142 +1,2 @@ | ||
| import { QueryClient } from '../core' | ||
| import { getLogger } from '../core/logger' | ||
| import { | ||
| dehydrate, | ||
| DehydratedState, | ||
| DehydrateOptions, | ||
| HydrateOptions, | ||
| hydrate, | ||
| } from 'react-query' | ||
| import { Promisable } from 'type-fest' | ||
|
|
||
| export interface Persister { | ||
| persistClient(persistClient: PersistedClient): Promisable<void> | ||
| restoreClient(): Promisable<PersistedClient | undefined> | ||
| removeClient(): Promisable<void> | ||
| } | ||
|
|
||
| export interface PersistedClient { | ||
| timestamp: number | ||
| buster: string | ||
| clientState: DehydratedState | ||
| } | ||
|
|
||
| export interface PersistQueryClienRootOptions { | ||
| /** The QueryClient to persist */ | ||
| queryClient: QueryClient | ||
| /** The Persister interface for storing and restoring the cache | ||
| * to/from a persisted location */ | ||
| persister: Persister | ||
| /** A unique string that can be used to forcefully | ||
| * invalidate existing caches if they do not share the same buster string */ | ||
| buster?: string | ||
| } | ||
|
|
||
| export interface PersistedQueryClientRestoreOptions | ||
| extends PersistQueryClienRootOptions { | ||
| /** The max-allowed age of the cache in milliseconds. | ||
| * If a persisted cache is found that is older than this | ||
| * time, it will be discarded */ | ||
| maxAge?: number | ||
| /** The options passed to the hydrate function */ | ||
| hydrateOptions?: HydrateOptions | ||
| } | ||
|
|
||
| export interface PersistedQueryClientSaveOptions | ||
| extends PersistQueryClienRootOptions { | ||
| /** The options passed to the dehydrate function */ | ||
| dehydrateOptions?: DehydrateOptions | ||
| } | ||
|
|
||
| export interface PersistQueryClientOptions | ||
| extends PersistedQueryClientRestoreOptions, | ||
| PersistedQueryClientSaveOptions, | ||
| PersistQueryClienRootOptions {} | ||
|
|
||
| /** | ||
| * Restores persisted data to the QueryCache | ||
| * - data obtained from persister.restoreClient | ||
| * - data is hydrated using hydrateOptions | ||
| * If data is expired, busted, empty, or throws, it runs persister.removeClient | ||
| */ | ||
| export async function persistQueryClientRestore({ | ||
| queryClient, | ||
| persister, | ||
| maxAge = 1000 * 60 * 60 * 24, | ||
| buster = '', | ||
| hydrateOptions, | ||
| }: PersistedQueryClientRestoreOptions) { | ||
| if (typeof window !== 'undefined') { | ||
| try { | ||
| const persistedClient = await persister.restoreClient() | ||
|
|
||
| if (persistedClient) { | ||
| if (persistedClient.timestamp) { | ||
| const expired = Date.now() - persistedClient.timestamp > maxAge | ||
| const busted = persistedClient.buster !== buster | ||
| if (expired || busted) { | ||
| persister.removeClient() | ||
| } else { | ||
| hydrate(queryClient, persistedClient.clientState, hydrateOptions) | ||
| } | ||
| } else { | ||
| persister.removeClient() | ||
| } | ||
| } | ||
| } catch (err) { | ||
| getLogger().error(err) | ||
| getLogger().warn( | ||
| 'Encountered an error attempting to restore client cache from persisted location. As a precaution, the persisted cache will be discarded.' | ||
| ) | ||
| persister.removeClient() | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Persists data from the QueryCache | ||
| * - data dehydrated using dehydrateOptions | ||
| * - data is persisted using persister.persistClient | ||
| */ | ||
| export async function persistQueryClientSave({ | ||
| queryClient, | ||
| persister, | ||
| buster = '', | ||
| dehydrateOptions, | ||
| }: PersistedQueryClientSaveOptions) { | ||
| if (typeof window !== 'undefined') { | ||
| const persistClient: PersistedClient = { | ||
| buster, | ||
| timestamp: Date.now(), | ||
| clientState: dehydrate(queryClient, dehydrateOptions), | ||
| } | ||
|
|
||
| await persister.persistClient(persistClient) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Subscribe to QueryCache updates (for persisting) | ||
| * @returns an unsubscribe function (to discontinue monitoring) | ||
| */ | ||
| export function persistQueryClientSubscribe( | ||
| props: PersistedQueryClientSaveOptions | ||
| ) { | ||
| return props.queryClient.getQueryCache().subscribe(() => { | ||
| persistQueryClientSave(props) | ||
| }) | ||
| } | ||
|
|
||
| /** | ||
| * Restores persisted data to QueryCache and persists further changes. | ||
| * (Retained for backwards compatibility) | ||
| */ | ||
| export async function persistQueryClient(props: PersistQueryClientOptions) { | ||
| if (typeof window !== 'undefined') { | ||
| // Attempt restore | ||
| await persistQueryClientRestore(props) | ||
|
|
||
| // Subscribe to changes in the query cache to trigger the save | ||
| return persistQueryClientSubscribe(props) | ||
| } | ||
| } | ||
| export * from './persist' | ||
| export * from './PersistQueryClientProvider' | ||
TkDodo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.