Scope query client per DID

This commit is contained in:
Dan Abramov
2024-03-22 00:06:25 +00:00
parent 8e8bcfbc75
commit 2e2e554f07
3 changed files with 65 additions and 31 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ function InnerApp() {
<React.Fragment <React.Fragment
// Resets the entire tree below when it changes: // Resets the entire tree below when it changes:
key={currentAccount?.did}> key={currentAccount?.did}>
<QueryProvider> <QueryProvider currentDid={currentAccount?.did}>
<PushNotificationsListener> <PushNotificationsListener>
<StatsigProvider> <StatsigProvider>
<LabelDefsProvider> <LabelDefsProvider>
+1 -1
View File
@@ -54,7 +54,7 @@ function InnerApp() {
<React.Fragment <React.Fragment
// Resets the entire tree below when it changes: // Resets the entire tree below when it changes:
key={currentAccount?.did}> key={currentAccount?.did}>
<QueryProvider> <QueryProvider currentDid={currentAccount?.did}>
<StatsigProvider> <StatsigProvider>
<LabelDefsProvider> <LabelDefsProvider>
<LoggedOutViewProvider> <LoggedOutViewProvider>
+45 -11
View File
@@ -1,4 +1,4 @@
import React from 'react' import React, {useRef, useState} from 'react'
import {AppState, AppStateStatus} from 'react-native' import {AppState, AppStateStatus} from 'react-native'
import AsyncStorage from '@react-native-async-storage/async-storage' import AsyncStorage from '@react-native-async-storage/async-storage'
import {createAsyncStoragePersister} from '@tanstack/query-async-storage-persister' import {createAsyncStoragePersister} from '@tanstack/query-async-storage-persister'
@@ -39,7 +39,8 @@ focusManager.setEventListener(onFocus => {
} }
}) })
const queryClient = new QueryClient({ const createQueryClient = () =>
new QueryClient({
defaultOptions: { defaultOptions: {
queries: { queries: {
// NOTE // NOTE
@@ -60,11 +61,6 @@ const queryClient = new QueryClient({
}, },
}) })
const asyncStoragePersister = createAsyncStoragePersister({
storage: AsyncStorage,
key: 'queryCache',
})
const dehydrateOptions: PersistQueryClientProviderProps['persistOptions']['dehydrateOptions'] = const dehydrateOptions: PersistQueryClientProviderProps['persistOptions']['dehydrateOptions'] =
{ {
shouldDehydrateMutation: (_: any) => false, shouldDehydrateMutation: (_: any) => false,
@@ -73,12 +69,50 @@ const dehydrateOptions: PersistQueryClientProviderProps['persistOptions']['dehyd
}, },
} }
const persistOptions = { export function QueryProvider({
persister: asyncStoragePersister, children,
dehydrateOptions, currentDid,
}: {
children: React.ReactNode
currentDid: string | undefined
}) {
return (
<QueryProviderInner
// Enforce we never reuse cache between users.
// These two props MUST stay in sync.
key={currentDid}
currentDid={currentDid}>
{children}
</QueryProviderInner>
)
} }
export function QueryProvider({children}: {children: React.ReactNode}) { function QueryProviderInner({
children,
currentDid,
}: {
children: React.ReactNode
currentDid: string | undefined
}) {
const initialDid = useRef(currentDid)
if (currentDid !== initialDid.current) {
throw Error(
'Something is very wrong. Expected did to be stable due to key above.',
)
}
// We create the query client here so that it's scoped to a specific DID.
// Do not move the query client creation outside of this component.
const [queryClient, _setQueryClient] = useState(() => createQueryClient())
const [persistOptions, _setPersistOptions] = useState(() => {
const asyncPersister = createAsyncStoragePersister({
storage: AsyncStorage,
key: 'queryClient-' + (currentDid ?? 'logged-out'),
})
return {
persister: asyncPersister,
dehydrateOptions,
}
})
return ( return (
<PersistQueryClientProvider <PersistQueryClientProvider
client={queryClient} client={queryClient}