···136 }
137 })
138}
139+export async function refetchConfig() {
140+ logger.debug(`refetchConfig: fetching...`)
141+ const res = await getConfig()
142+ qc.setQueryData<AppBskyAgeassuranceGetConfig.OutputSchema>(
143+ configQueryKey,
144+ res,
145+ )
146+ return res
147+}
148export function useConfigQuery() {
149 return useQuery(
150 {
···155 * @see https://tanstack.com/query/latest/docs/framework/react/guides/initial-query-data#initial-data-from-the-cache-with-initialdataupdatedat
156 */
157 staleTime: IS_DEV ? 5e3 : 1000 * 60 * 60,
158+ /**
159+ * N.B. if prefetch failed above, we'll have no `initialData`, and this
160+ * query will run on startup.
161+ */
162 initialData: getConfigFromCache(),
163 initialDataUpdatedAt: () =>
164 qc.getQueryState(configQueryKey)?.dataUpdatedAt,
+9-2
src/ageAssurance/state.ts
···30 access: AgeAssuranceAccess.Safe,
31 }
3233- // should never happen, but need to guard
00000034 if (!config) {
35 logger.warn('useAgeAssuranceState: missing config')
36 return {
37 status: AgeAssuranceStatus.Unknown,
38- access: AgeAssuranceAccess.Unknown,
039 }
40 }
41
···30 access: AgeAssuranceAccess.Safe,
31 }
3233+ /**
34+ * This can happen if the prefetch fails (such as due to network issues).
35+ * The query handler will try it again, but if it continues to fail, of
36+ * course we won't have config.
37+ *
38+ * In this case, fail open to avoid blocking users.
39+ */
40 if (!config) {
41 logger.warn('useAgeAssuranceState: missing config')
42 return {
43 status: AgeAssuranceStatus.Unknown,
44+ access: AgeAssuranceAccess.Safe,
45+ error: 'config',
46 }
47 }
48
···3import {useLingui} from '@lingui/react'
45import {atoms as a, select, useTheme, type ViewStyleProp} from '#/alf'
06import {useDialogControl} from '#/components/ageAssurance/AgeAssuranceInitDialog'
7import type * as Dialog from '#/components/Dialog'
8import {ShieldCheck_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
···19 const aa = useAgeAssurance()
2021 if (aa.state.access === aa.Access.Full) return null
0002223 return (
24 <Inner style={style} control={control}>
···3import {useLingui} from '@lingui/react'
45import {atoms as a, select, useTheme, type ViewStyleProp} from '#/alf'
6+import {AgeAssuranceConfigUnavailableError} from '#/components/ageAssurance/AgeAssuranceErrors'
7import {useDialogControl} from '#/components/ageAssurance/AgeAssuranceInitDialog'
8import type * as Dialog from '#/components/Dialog'
9import {ShieldCheck_Stroke2_Corner0_Rounded as Shield} from '#/components/icons/Shield'
···20 const aa = useAgeAssurance()
2122 if (aa.state.access === aa.Access.Full) return null
23+ if (aa.state.error === 'config') {
24+ return <AgeAssuranceConfigUnavailableError style={style} />
25+ }
2627 return (
28 <Inner style={style} control={control}>