mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react' 2import {AppState, AppStateStatus} from 'react-native' 3import AsyncStorage from '@react-native-async-storage/async-storage' 4import {createAsyncStoragePersister} from '@tanstack/query-async-storage-persister' 5import {focusManager, QueryClient} from '@tanstack/react-query' 6import { 7 PersistQueryClientProvider, 8 PersistQueryClientProviderProps, 9} from '@tanstack/react-query-persist-client' 10 11import {isNative} from '#/platform/detection' 12 13// any query keys in this array will be persisted to AsyncStorage 14const STORED_CACHE_QUERY_KEYS = ['labelers-detailed-info'] 15 16focusManager.setEventListener(onFocus => { 17 if (isNative) { 18 const subscription = AppState.addEventListener( 19 'change', 20 (status: AppStateStatus) => { 21 focusManager.setFocused(status === 'active') 22 }, 23 ) 24 25 return () => subscription.remove() 26 } else if (typeof window !== 'undefined' && window.addEventListener) { 27 // these handlers are a bit redundant but focus catches when the browser window 28 // is blurred/focused while visibilitychange seems to only handle when the 29 // window minimizes (both of them catch tab changes) 30 // there's no harm to redundant fires because refetchOnWindowFocus is only 31 // used with queries that employ stale data times 32 const handler = () => onFocus() 33 window.addEventListener('focus', handler, false) 34 window.addEventListener('visibilitychange', handler, false) 35 return () => { 36 window.removeEventListener('visibilitychange', handler) 37 window.removeEventListener('focus', handler) 38 } 39 } 40}) 41 42const queryClient = new QueryClient({ 43 defaultOptions: { 44 queries: { 45 // NOTE 46 // refetchOnWindowFocus breaks some UIs (like feeds) 47 // so we only selectively want to enable this 48 // -prf 49 refetchOnWindowFocus: false, 50 // Structural sharing between responses makes it impossible to rely on 51 // "first seen" timestamps on objects to determine if they're fresh. 52 // Disable this optimization so that we can rely on "first seen" timestamps. 53 structuralSharing: false, 54 // We don't want to retry queries by default, because in most cases we 55 // want to fail early and show a response to the user. There are 56 // exceptions, and those can be made on a per-query basis. For others, we 57 // should give users controls to retry. 58 retry: false, 59 }, 60 }, 61}) 62 63const asyncStoragePersister = createAsyncStoragePersister({ 64 storage: AsyncStorage, 65 key: 'queryCache', 66}) 67 68const dehydrateOptions: PersistQueryClientProviderProps['persistOptions']['dehydrateOptions'] = 69 { 70 shouldDehydrateMutation: (_: any) => false, 71 shouldDehydrateQuery: query => { 72 return STORED_CACHE_QUERY_KEYS.includes(String(query.queryKey[0])) 73 }, 74 } 75 76const persistOptions = { 77 persister: asyncStoragePersister, 78 dehydrateOptions, 79} 80 81export function QueryProvider({children}: {children: React.ReactNode}) { 82 return ( 83 <PersistQueryClientProvider 84 client={queryClient} 85 persistOptions={persistOptions}> 86 {children} 87 </PersistQueryClientProvider> 88 ) 89}