about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/react-query.tsx5
-rw-r--r--src/state/queries/actor-autocomplete.ts13
-rw-r--r--src/state/queries/actor-search.ts7
-rw-r--r--src/state/queries/app-passwords.ts5
-rw-r--r--src/state/queries/feed.ts31
-rw-r--r--src/state/queries/handle.ts13
-rw-r--r--src/state/queries/invites.ts8
-rw-r--r--src/state/queries/labeler.ts14
-rw-r--r--src/state/queries/list-members.ts9
-rw-r--r--src/state/queries/list-memberships.ts7
-rw-r--r--src/state/queries/list.ts18
-rw-r--r--src/state/queries/my-blocked-accounts.ts7
-rw-r--r--src/state/queries/my-follows.ts6
-rw-r--r--src/state/queries/my-lists.ts10
-rw-r--r--src/state/queries/my-muted-accounts.ts7
-rw-r--r--src/state/queries/notifications/feed.ts20
-rw-r--r--src/state/queries/post-feed.ts7
-rw-r--r--src/state/queries/post-reposted-by.ts7
-rw-r--r--src/state/queries/post-thread.ts15
-rw-r--r--src/state/queries/post.ts3
-rw-r--r--src/state/queries/preferences/index.ts33
-rw-r--r--src/state/queries/profile-feedgens.ts5
-rw-r--r--src/state/queries/profile-followers.ts7
-rw-r--r--src/state/queries/profile-follows.ts9
-rw-r--r--src/state/queries/profile-lists.ts6
-rw-r--r--src/state/queries/profile.ts16
-rw-r--r--src/state/queries/resolve-uri.ts9
-rw-r--r--src/state/queries/search-posts.ts9
-rw-r--r--src/state/queries/service.ts3
-rw-r--r--src/state/queries/suggested-feeds.ts7
-rw-r--r--src/state/queries/suggested-follows.ts21
31 files changed, 198 insertions, 139 deletions
diff --git a/src/lib/react-query.tsx b/src/lib/react-query.tsx
index 2fcd46942..be507216a 100644
--- a/src/lib/react-query.tsx
+++ b/src/lib/react-query.tsx
@@ -11,7 +11,8 @@ import {
 import {isNative} from '#/platform/detection'
 
 // any query keys in this array will be persisted to AsyncStorage
-const STORED_CACHE_QUERY_KEYS = ['labelers-detailed-info']
+export const labelersDetailedInfoQueryKeyRoot = 'labelers-detailed-info'
+const STORED_CACHE_QUERY_KEY_ROOTS = [labelersDetailedInfoQueryKeyRoot]
 
 focusManager.setEventListener(onFocus => {
   if (isNative) {
@@ -65,7 +66,7 @@ const dehydrateOptions: PersistQueryClientProviderProps['persistOptions']['dehyd
   {
     shouldDehydrateMutation: (_: any) => false,
     shouldDehydrateQuery: query => {
-      return STORED_CACHE_QUERY_KEYS.includes(String(query.queryKey[0]))
+      return STORED_CACHE_QUERY_KEY_ROOTS.includes(String(query.queryKey[0]))
     },
   }
 
diff --git a/src/state/queries/actor-autocomplete.ts b/src/state/queries/actor-autocomplete.ts
index e6bf04ba3..c3fcb92fb 100644
--- a/src/state/queries/actor-autocomplete.ts
+++ b/src/state/queries/actor-autocomplete.ts
@@ -1,21 +1,22 @@
 import React from 'react'
-import {AppBskyActorDefs, ModerationOpts, moderateProfile} from '@atproto/api'
+import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api'
 import {useQuery, useQueryClient} from '@tanstack/react-query'
 
+import {isJustAMute} from '#/lib/moderation'
+import {isInvalidHandle} from '#/lib/strings/handles'
 import {logger} from '#/logger'
-import {getAgent} from '#/state/session'
-import {useMyFollowsQuery} from '#/state/queries/my-follows'
 import {STALE} from '#/state/queries'
+import {useMyFollowsQuery} from '#/state/queries/my-follows'
+import {getAgent} from '#/state/session'
 import {DEFAULT_LOGGED_OUT_PREFERENCES, useModerationOpts} from './preferences'
-import {isInvalidHandle} from '#/lib/strings/handles'
-import {isJustAMute} from '#/lib/moderation'
 
 const DEFAULT_MOD_OPTS = {
   userDid: undefined,
   prefs: DEFAULT_LOGGED_OUT_PREFERENCES.moderationPrefs,
 }
 
-export const RQKEY = (prefix: string) => ['actor-autocomplete', prefix]
+const RQKEY_ROOT = 'actor-autocomplete'
+export const RQKEY = (prefix: string) => [RQKEY_ROOT, prefix]
 
 export function useActorAutocompleteQuery(prefix: string) {
   const {data: follows, isFetching} = useMyFollowsQuery()
diff --git a/src/state/queries/actor-search.ts b/src/state/queries/actor-search.ts
index f72511548..7123736df 100644
--- a/src/state/queries/actor-search.ts
+++ b/src/state/queries/actor-search.ts
@@ -1,10 +1,11 @@
 import {AppBskyActorDefs} from '@atproto/api'
 import {QueryClient, useQuery} from '@tanstack/react-query'
 
-import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
+import {getAgent} from '#/state/session'
 
-export const RQKEY = (prefix: string) => ['actor-search', prefix]
+const RQKEY_ROOT = 'actor-search'
+export const RQKEY = (prefix: string) => [RQKEY_ROOT, prefix]
 
 export function useActorSearch(prefix: string) {
   return useQuery<AppBskyActorDefs.ProfileView[]>({
@@ -26,7 +27,7 @@ export function* findAllProfilesInQueryData(
 ) {
   const queryDatas = queryClient.getQueriesData<AppBskyActorDefs.ProfileView[]>(
     {
-      queryKey: ['actor-search'],
+      queryKey: [RQKEY_ROOT],
     },
   )
   for (const [_queryKey, queryData] of queryDatas) {
diff --git a/src/state/queries/app-passwords.ts b/src/state/queries/app-passwords.ts
index 014244f01..ddfe6643d 100644
--- a/src/state/queries/app-passwords.ts
+++ b/src/state/queries/app-passwords.ts
@@ -1,10 +1,11 @@
 import {ComAtprotoServerCreateAppPassword} from '@atproto/api'
-import {useQuery, useQueryClient, useMutation} from '@tanstack/react-query'
+import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 
 import {STALE} from '#/state/queries'
 import {getAgent} from '../session'
 
-export const RQKEY = () => ['app-passwords']
+const RQKEY_ROOT = 'app-passwords'
+export const RQKEY = () => [RQKEY_ROOT]
 
 export function useAppPasswordsQuery() {
   return useQuery({
diff --git a/src/state/queries/feed.ts b/src/state/queries/feed.ts
index 1fa92c291..c56912491 100644
--- a/src/state/queries/feed.ts
+++ b/src/state/queries/feed.ts
@@ -1,24 +1,24 @@
 import {
-  useQuery,
-  useInfiniteQuery,
-  InfiniteData,
-  QueryKey,
-  useMutation,
-} from '@tanstack/react-query'
-import {
-  AtUri,
-  RichText,
   AppBskyFeedDefs,
   AppBskyGraphDefs,
   AppBskyUnspeccedGetPopularFeedGenerators,
+  AtUri,
+  RichText,
 } from '@atproto/api'
+import {
+  InfiniteData,
+  QueryKey,
+  useInfiniteQuery,
+  useMutation,
+  useQuery,
+} from '@tanstack/react-query'
 
-import {router} from '#/routes'
 import {sanitizeDisplayName} from '#/lib/strings/display-names'
 import {sanitizeHandle} from '#/lib/strings/handles'
-import {getAgent} from '#/state/session'
-import {usePreferencesQuery} from '#/state/queries/preferences'
 import {STALE} from '#/state/queries'
+import {usePreferencesQuery} from '#/state/queries/preferences'
+import {getAgent} from '#/state/session'
+import {router} from '#/routes'
 
 export type FeedSourceFeedInfo = {
   type: 'feed'
@@ -56,8 +56,9 @@ export type FeedSourceListInfo = {
 
 export type FeedSourceInfo = FeedSourceFeedInfo | FeedSourceListInfo
 
+const feedSourceInfoQueryKeyRoot = 'getFeedSourceInfo'
 export const feedSourceInfoQueryKey = ({uri}: {uri: string}) => [
-  'getFeedSourceInfo',
+  feedSourceInfoQueryKeyRoot,
   uri,
 ]
 
@@ -216,6 +217,8 @@ const FOLLOWING_FEED_STUB: FeedSourceInfo = {
   likeUri: '',
 }
 
+const pinnedFeedInfosQueryKeyRoot = 'pinnedFeedsInfos'
+
 export function usePinnedFeedsInfos() {
   const {data: preferences, isLoading: isLoadingPrefs} = usePreferencesQuery()
   const pinnedUris = preferences?.feeds?.pinned ?? []
@@ -223,7 +226,7 @@ export function usePinnedFeedsInfos() {
   return useQuery({
     staleTime: STALE.INFINITY,
     enabled: !isLoadingPrefs,
-    queryKey: ['pinnedFeedsInfos', pinnedUris.join(',')],
+    queryKey: [pinnedFeedInfosQueryKeyRoot, pinnedUris.join(',')],
     queryFn: async () => {
       let resolved = new Map()
 
diff --git a/src/state/queries/handle.ts b/src/state/queries/handle.ts
index d7c411699..ddeb35ce7 100644
--- a/src/state/queries/handle.ts
+++ b/src/state/queries/handle.ts
@@ -1,11 +1,16 @@
 import React from 'react'
-import {useQueryClient, useMutation} from '@tanstack/react-query'
+import {useMutation, useQueryClient} from '@tanstack/react-query'
 
-import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
+import {getAgent} from '#/state/session'
 
-const fetchHandleQueryKey = (handleOrDid: string) => ['handle', handleOrDid]
-const fetchDidQueryKey = (handleOrDid: string) => ['did', handleOrDid]
+const handleQueryKeyRoot = 'handle'
+const fetchHandleQueryKey = (handleOrDid: string) => [
+  handleQueryKeyRoot,
+  handleOrDid,
+]
+const didQueryKeyRoot = 'did'
+const fetchDidQueryKey = (handleOrDid: string) => [didQueryKeyRoot, handleOrDid]
 
 export function useFetchHandle() {
   const queryClient = useQueryClient()
diff --git a/src/state/queries/invites.ts b/src/state/queries/invites.ts
index 9ae9c707f..d5d6ecf97 100644
--- a/src/state/queries/invites.ts
+++ b/src/state/queries/invites.ts
@@ -1,14 +1,16 @@
 import {ComAtprotoServerDefs} from '@atproto/api'
 import {useQuery} from '@tanstack/react-query'
 
-import {getAgent} from '#/state/session'
-import {STALE} from '#/state/queries'
 import {cleanError} from '#/lib/strings/errors'
+import {STALE} from '#/state/queries'
+import {getAgent} from '#/state/session'
 
 function isInviteAvailable(invite: ComAtprotoServerDefs.InviteCode): boolean {
   return invite.available - invite.uses.length > 0 && !invite.disabled
 }
 
+const inviteCodesQueryKeyRoot = 'inviteCodes'
+
 export type InviteCodesQueryResponse = Exclude<
   ReturnType<typeof useInviteCodesQuery>['data'],
   undefined
@@ -16,7 +18,7 @@ export type InviteCodesQueryResponse = Exclude<
 export function useInviteCodesQuery() {
   return useQuery({
     staleTime: STALE.MINUTES.FIVE,
-    queryKey: ['inviteCodes'],
+    queryKey: [inviteCodesQueryKeyRoot],
     queryFn: async () => {
       const res = await getAgent()
         .com.atproto.server.getAccountInviteCodes({})
diff --git a/src/state/queries/labeler.ts b/src/state/queries/labeler.ts
index e2df6959a..78301eb0d 100644
--- a/src/state/queries/labeler.ts
+++ b/src/state/queries/labeler.ts
@@ -2,17 +2,25 @@ import {AppBskyLabelerDefs} from '@atproto/api'
 import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 import {z} from 'zod'
 
+import {labelersDetailedInfoQueryKeyRoot} from '#/lib/react-query'
 import {STALE} from '#/state/queries'
 import {preferencesQueryKey} from '#/state/queries/preferences'
 import {getAgent} from '#/state/session'
 
-export const labelerInfoQueryKey = (did: string) => ['labeler-info', did]
+const labelerInfoQueryKeyRoot = 'labeler-info'
+export const labelerInfoQueryKey = (did: string) => [
+  labelerInfoQueryKeyRoot,
+  did,
+]
+
+const labelersInfoQueryKeyRoot = 'labelers-info'
 export const labelersInfoQueryKey = (dids: string[]) => [
-  'labelers-info',
+  labelersInfoQueryKeyRoot,
   dids.slice().sort(),
 ]
+
 export const labelersDetailedInfoQueryKey = (dids: string[]) => [
-  'labelers-detailed-info',
+  labelersDetailedInfoQueryKeyRoot,
   dids,
 ]
 
diff --git a/src/state/queries/list-members.ts b/src/state/queries/list-members.ts
index d84089c90..87a409b88 100644
--- a/src/state/queries/list-members.ts
+++ b/src/state/queries/list-members.ts
@@ -1,18 +1,19 @@
 import {AppBskyActorDefs, AppBskyGraphGetList} from '@atproto/api'
 import {
-  useInfiniteQuery,
   InfiniteData,
   QueryClient,
   QueryKey,
+  useInfiniteQuery,
 } from '@tanstack/react-query'
 
-import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
+import {getAgent} from '#/state/session'
 
 const PAGE_SIZE = 30
 type RQPageParam = string | undefined
 
-export const RQKEY = (uri: string) => ['list-members', uri]
+const RQKEY_ROOT = 'list-members'
+export const RQKEY = (uri: string) => [RQKEY_ROOT, uri]
 
 export function useListMembersQuery(uri: string) {
   return useInfiniteQuery<
@@ -44,7 +45,7 @@ export function* findAllProfilesInQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyGraphGetList.OutputSchema>
   >({
-    queryKey: ['list-members'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData) {
diff --git a/src/state/queries/list-memberships.ts b/src/state/queries/list-memberships.ts
index 6cae3fa2e..d5ddd5a70 100644
--- a/src/state/queries/list-memberships.ts
+++ b/src/state/queries/list-memberships.ts
@@ -17,16 +17,17 @@
 import {AtUri} from '@atproto/api'
 import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 
-import {useSession, getAgent} from '#/state/session'
-import {RQKEY as LIST_MEMBERS_RQKEY} from '#/state/queries/list-members'
 import {STALE} from '#/state/queries'
+import {RQKEY as LIST_MEMBERS_RQKEY} from '#/state/queries/list-members'
+import {getAgent, useSession} from '#/state/session'
 
 // sanity limit is SANITY_PAGE_LIMIT*PAGE_SIZE total records
 const SANITY_PAGE_LIMIT = 1000
 const PAGE_SIZE = 100
 // ...which comes 100,000k list members
 
-export const RQKEY = () => ['list-memberships']
+const RQKEY_ROOT = 'list-memberships'
+export const RQKEY = () => [RQKEY_ROOT]
 
 export interface ListMembersip {
   membershipUri: string
diff --git a/src/state/queries/list.ts b/src/state/queries/list.ts
index 845658a27..c653d5376 100644
--- a/src/state/queries/list.ts
+++ b/src/state/queries/list.ts
@@ -1,21 +1,23 @@
+import {Image as RNImage} from 'react-native-image-crop-picker'
 import {
-  AtUri,
+  AppBskyGraphDefs,
   AppBskyGraphGetList,
   AppBskyGraphList,
-  AppBskyGraphDefs,
+  AtUri,
   Facet,
 } from '@atproto/api'
-import {Image as RNImage} from 'react-native-image-crop-picker'
-import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
+import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 import chunk from 'lodash.chunk'
-import {useSession, getAgent} from '../session'
-import {invalidate as invalidateMyLists} from './my-lists'
-import {RQKEY as PROFILE_LISTS_RQKEY} from './profile-lists'
+
 import {uploadBlob} from '#/lib/api'
 import {until} from '#/lib/async/until'
 import {STALE} from '#/state/queries'
+import {getAgent, useSession} from '../session'
+import {invalidate as invalidateMyLists} from './my-lists'
+import {RQKEY as PROFILE_LISTS_RQKEY} from './profile-lists'
 
-export const RQKEY = (uri: string) => ['list', uri]
+const RQKEY_ROOT = 'list'
+export const RQKEY = (uri: string) => [RQKEY_ROOT, uri]
 
 export function useListQuery(uri?: string) {
   return useQuery<AppBskyGraphDefs.ListView, Error>({
diff --git a/src/state/queries/my-blocked-accounts.ts b/src/state/queries/my-blocked-accounts.ts
index badaaec34..36b9ac580 100644
--- a/src/state/queries/my-blocked-accounts.ts
+++ b/src/state/queries/my-blocked-accounts.ts
@@ -1,14 +1,15 @@
 import {AppBskyActorDefs, AppBskyGraphGetBlocks} from '@atproto/api'
 import {
-  useInfiniteQuery,
   InfiniteData,
   QueryClient,
   QueryKey,
+  useInfiniteQuery,
 } from '@tanstack/react-query'
 
 import {getAgent} from '#/state/session'
 
-export const RQKEY = () => ['my-blocked-accounts']
+const RQKEY_ROOT = 'my-blocked-accounts'
+export const RQKEY = () => [RQKEY_ROOT]
 type RQPageParam = string | undefined
 
 export function useMyBlockedAccountsQuery() {
@@ -39,7 +40,7 @@ export function* findAllProfilesInQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyGraphGetBlocks.OutputSchema>
   >({
-    queryKey: ['my-blocked-accounts'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
diff --git a/src/state/queries/my-follows.ts b/src/state/queries/my-follows.ts
index f95c3f5a7..a130347f8 100644
--- a/src/state/queries/my-follows.ts
+++ b/src/state/queries/my-follows.ts
@@ -1,14 +1,16 @@
 import {AppBskyActorDefs} from '@atproto/api'
 import {useQuery} from '@tanstack/react-query'
-import {useSession, getAgent} from '../session'
+
 import {STALE} from '#/state/queries'
+import {getAgent, useSession} from '../session'
 
 // sanity limit is SANITY_PAGE_LIMIT*PAGE_SIZE total records
 const SANITY_PAGE_LIMIT = 1000
 const PAGE_SIZE = 100
 // ...which comes 10,000k follows
 
-export const RQKEY = () => ['my-follows']
+const RQKEY_ROOT = 'my-follows'
+export const RQKEY = () => [RQKEY_ROOT]
 
 export function useMyFollowsQuery() {
   const {currentAccount} = useSession()
diff --git a/src/state/queries/my-lists.ts b/src/state/queries/my-lists.ts
index d53e13032..284b757c6 100644
--- a/src/state/queries/my-lists.ts
+++ b/src/state/queries/my-lists.ts
@@ -1,16 +1,18 @@
 import {AppBskyGraphDefs} from '@atproto/api'
-import {useQuery, QueryClient} from '@tanstack/react-query'
+import {QueryClient, useQuery} from '@tanstack/react-query'
 
 import {accumulate} from '#/lib/async/accumulate'
-import {useSession, getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
+import {getAgent, useSession} from '#/state/session'
 
 export type MyListsFilter =
   | 'all'
   | 'curate'
   | 'mod'
   | 'all-including-subscribed'
-export const RQKEY = (filter: MyListsFilter) => ['my-lists', filter]
+
+const RQKEY_ROOT = 'my-lists'
+export const RQKEY = (filter: MyListsFilter) => [RQKEY_ROOT, filter]
 
 export function useMyListsQuery(filter: MyListsFilter) {
   const {currentAccount} = useSession()
@@ -91,6 +93,6 @@ export function invalidate(qc: QueryClient, filter?: MyListsFilter) {
   if (filter) {
     qc.invalidateQueries({queryKey: RQKEY(filter)})
   } else {
-    qc.invalidateQueries({queryKey: ['my-lists']})
+    qc.invalidateQueries({queryKey: [RQKEY_ROOT]})
   }
 }
diff --git a/src/state/queries/my-muted-accounts.ts b/src/state/queries/my-muted-accounts.ts
index 8929e04d3..9e90044bf 100644
--- a/src/state/queries/my-muted-accounts.ts
+++ b/src/state/queries/my-muted-accounts.ts
@@ -1,14 +1,15 @@
 import {AppBskyActorDefs, AppBskyGraphGetMutes} from '@atproto/api'
 import {
-  useInfiniteQuery,
   InfiniteData,
   QueryClient,
   QueryKey,
+  useInfiniteQuery,
 } from '@tanstack/react-query'
 
 import {getAgent} from '#/state/session'
 
-export const RQKEY = () => ['my-muted-accounts']
+const RQKEY_ROOT = 'my-muted-accounts'
+export const RQKEY = () => [RQKEY_ROOT]
 type RQPageParam = string | undefined
 
 export function useMyMutedAccountsQuery() {
@@ -39,7 +40,7 @@ export function* findAllProfilesInQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyGraphGetMutes.OutputSchema>
   >({
-    queryKey: ['my-muted-accounts'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
diff --git a/src/state/queries/notifications/feed.ts b/src/state/queries/notifications/feed.ts
index 405d054d4..b4bdd741e 100644
--- a/src/state/queries/notifications/feed.ts
+++ b/src/state/queries/notifications/feed.ts
@@ -19,28 +19,30 @@
 import {useEffect, useRef} from 'react'
 import {AppBskyFeedDefs} from '@atproto/api'
 import {
-  useInfiniteQuery,
   InfiniteData,
+  QueryClient,
   QueryKey,
+  useInfiniteQuery,
   useQueryClient,
-  QueryClient,
 } from '@tanstack/react-query'
-import {useModerationOpts} from '../preferences'
-import {useUnreadNotificationsApi} from './unread'
-import {fetchPage} from './util'
-import {FeedPage} from './types'
+
 import {useMutedThreads} from '#/state/muted-threads'
 import {STALE} from '..'
+import {useModerationOpts} from '../preferences'
 import {embedViewRecordToPostView, getEmbeddedPost} from '../util'
+import {FeedPage} from './types'
+import {useUnreadNotificationsApi} from './unread'
+import {fetchPage} from './util'
 
-export type {NotificationType, FeedNotification, FeedPage} from './types'
+export type {FeedNotification, FeedPage, NotificationType} from './types'
 
 const PAGE_SIZE = 30
 
 type RQPageParam = string | undefined
 
+const RQKEY_ROOT = 'notification-feed'
 export function RQKEY() {
-  return ['notification-feed']
+  return [RQKEY_ROOT]
 }
 
 export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
@@ -138,7 +140,7 @@ export function* findAllPostsInQueryData(
   uri: string,
 ): Generator<AppBskyFeedDefs.PostView, void> {
   const queryDatas = queryClient.getQueriesData<InfiniteData<FeedPage>>({
-    queryKey: ['notification-feed'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index b89888197..ee22bac69 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -58,8 +58,9 @@ export interface FeedParams {
 
 type RQPageParam = {cursor: string | undefined; api: FeedAPI} | undefined
 
+const RQKEY_ROOT = 'post-feed'
 export function RQKEY(feedDesc: FeedDescriptor, params?: FeedParams) {
-  return ['post-feed', feedDesc, params || {}]
+  return [RQKEY_ROOT, feedDesc, params || {}]
 }
 
 export interface FeedPostSliceItem {
@@ -402,7 +403,7 @@ export function* findAllPostsInQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<FeedPageUnselected>
   >({
-    queryKey: ['post-feed'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
@@ -467,7 +468,7 @@ export function resetProfilePostsQueries(
     queryClient.resetQueries({
       predicate: query =>
         !!(
-          query.queryKey[0] === 'post-feed' &&
+          query.queryKey[0] === RQKEY_ROOT &&
           (query.queryKey[1] as string)?.includes(did)
         ),
     })
diff --git a/src/state/queries/post-reposted-by.ts b/src/state/queries/post-reposted-by.ts
index db5fa6514..f8cfff0d2 100644
--- a/src/state/queries/post-reposted-by.ts
+++ b/src/state/queries/post-reposted-by.ts
@@ -1,9 +1,9 @@
 import {AppBskyActorDefs, AppBskyFeedGetRepostedBy} from '@atproto/api'
 import {
-  useInfiniteQuery,
   InfiniteData,
   QueryClient,
   QueryKey,
+  useInfiniteQuery,
 } from '@tanstack/react-query'
 
 import {getAgent} from '#/state/session'
@@ -12,7 +12,8 @@ const PAGE_SIZE = 30
 type RQPageParam = string | undefined
 
 // TODO refactor invalidate on mutate?
-export const RQKEY = (resolvedUri: string) => ['post-reposted-by', resolvedUri]
+const RQKEY_ROOT = 'post-reposted-by'
+export const RQKEY = (resolvedUri: string) => [RQKEY_ROOT, resolvedUri]
 
 export function usePostRepostedByQuery(resolvedUri: string | undefined) {
   return useInfiniteQuery<
@@ -44,7 +45,7 @@ export function* findAllProfilesInQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyFeedGetRepostedBy.OutputSchema>
   >({
-    queryKey: ['post-reposted-by'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
diff --git a/src/state/queries/post-thread.ts b/src/state/queries/post-thread.ts
index 26d40599c..832794bf5 100644
--- a/src/state/queries/post-thread.ts
+++ b/src/state/queries/post-thread.ts
@@ -1,19 +1,20 @@
 import {
+  AppBskyEmbedRecord,
   AppBskyFeedDefs,
-  AppBskyFeedPost,
   AppBskyFeedGetPostThread,
-  AppBskyEmbedRecord,
+  AppBskyFeedPost,
 } from '@atproto/api'
-import {useQuery, useQueryClient, QueryClient} from '@tanstack/react-query'
+import {QueryClient, useQuery, useQueryClient} from '@tanstack/react-query'
 
-import {getAgent} from '#/state/session'
 import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
-import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from './post-feed'
+import {getAgent} from '#/state/session'
 import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from './notifications/feed'
+import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from './post-feed'
 import {precacheThreadPostProfiles} from './profile'
 import {getEmbeddedPost} from './util'
 
-export const RQKEY = (uri: string) => ['post-thread', uri]
+const RQKEY_ROOT = 'post-thread'
+export const RQKEY = (uri: string) => [RQKEY_ROOT, uri]
 type ThreadViewNode = AppBskyFeedGetPostThread.OutputSchema['thread']
 
 export interface ThreadCtx {
@@ -233,7 +234,7 @@ export function* findAllPostsInQueryData(
   uri: string,
 ): Generator<ThreadNode, void> {
   const queryDatas = queryClient.getQueriesData<ThreadNode>({
-    queryKey: ['post-thread'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData) {
diff --git a/src/state/queries/post.ts b/src/state/queries/post.ts
index b868a1dac..746dedad2 100644
--- a/src/state/queries/post.ts
+++ b/src/state/queries/post.ts
@@ -9,7 +9,8 @@ import {updatePostShadow} from '#/state/cache/post-shadow'
 import {Shadow} from '#/state/cache/types'
 import {getAgent} from '#/state/session'
 
-export const RQKEY = (postUri: string) => ['post', postUri]
+const RQKEY_ROOT = 'post'
+export const RQKEY = (postUri: string) => [RQKEY_ROOT, postUri]
 
 export function usePostQuery(uri: string | undefined) {
   return useQuery<AppBskyFeedDefs.PostView>({
diff --git a/src/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts
index f9cd59cda..85e3f9a25 100644
--- a/src/state/queries/preferences/index.ts
+++ b/src/state/queries/preferences/index.ts
@@ -1,35 +1,36 @@
-import {useMemo, createContext, useContext} from 'react'
-import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
+import {createContext, useContext, useMemo} from 'react'
 import {
-  LabelPreference,
-  BskyFeedViewPreference,
-  ModerationOpts,
   AppBskyActorDefs,
   BSKY_LABELER_DID,
+  BskyFeedViewPreference,
+  LabelPreference,
+  ModerationOpts,
 } from '@atproto/api'
+import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 
 import {track} from '#/lib/analytics/analytics'
 import {getAge} from '#/lib/strings/time'
-import {getAgent, useSession} from '#/state/session'
-import {
-  UsePreferencesQueryResponse,
-  ThreadViewPreferences,
-} from '#/state/queries/preferences/types'
+import {useHiddenPosts, useLabelDefinitions} from '#/state/preferences'
+import {STALE} from '#/state/queries'
 import {
   DEFAULT_HOME_FEED_PREFS,
-  DEFAULT_THREAD_VIEW_PREFS,
   DEFAULT_LOGGED_OUT_PREFERENCES,
+  DEFAULT_THREAD_VIEW_PREFS,
 } from '#/state/queries/preferences/const'
 import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/moderation'
-import {STALE} from '#/state/queries'
-import {useHiddenPosts, useLabelDefinitions} from '#/state/preferences'
+import {
+  ThreadViewPreferences,
+  UsePreferencesQueryResponse,
+} from '#/state/queries/preferences/types'
+import {getAgent, useSession} from '#/state/session'
 import {saveLabelers} from '#/state/session/agent-config'
 
-export * from '#/state/queries/preferences/types'
-export * from '#/state/queries/preferences/moderation'
 export * from '#/state/queries/preferences/const'
+export * from '#/state/queries/preferences/moderation'
+export * from '#/state/queries/preferences/types'
 
-export const preferencesQueryKey = ['getPreferences']
+const preferencesQueryKeyRoot = 'getPreferences'
+export const preferencesQueryKey = [preferencesQueryKeyRoot]
 
 export function usePreferencesQuery() {
   return useQuery({
diff --git a/src/state/queries/profile-feedgens.ts b/src/state/queries/profile-feedgens.ts
index 7d33eb9c8..c690be197 100644
--- a/src/state/queries/profile-feedgens.ts
+++ b/src/state/queries/profile-feedgens.ts
@@ -1,5 +1,5 @@
 import {AppBskyFeedGetActorFeeds} from '@atproto/api'
-import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
+import {InfiniteData, QueryKey, useInfiniteQuery} from '@tanstack/react-query'
 
 import {getAgent} from '#/state/session'
 
@@ -7,7 +7,8 @@ const PAGE_SIZE = 30
 type RQPageParam = string | undefined
 
 // TODO refactor invalidate on mutate?
-export const RQKEY = (did: string) => ['profile-feedgens', did]
+const RQKEY_ROOT = 'profile-feedgens'
+export const RQKEY = (did: string) => [RQKEY_ROOT, did]
 
 export function useProfileFeedgensQuery(
   did: string,
diff --git a/src/state/queries/profile-followers.ts b/src/state/queries/profile-followers.ts
index fdefc8253..d7dfe25c6 100644
--- a/src/state/queries/profile-followers.ts
+++ b/src/state/queries/profile-followers.ts
@@ -1,9 +1,9 @@
 import {AppBskyActorDefs, AppBskyGraphGetFollowers} from '@atproto/api'
 import {
-  useInfiniteQuery,
   InfiniteData,
   QueryClient,
   QueryKey,
+  useInfiniteQuery,
 } from '@tanstack/react-query'
 
 import {getAgent} from '#/state/session'
@@ -11,7 +11,8 @@ import {getAgent} from '#/state/session'
 const PAGE_SIZE = 30
 type RQPageParam = string | undefined
 
-export const RQKEY = (did: string) => ['profile-followers', did]
+const RQKEY_ROOT = 'profile-followers'
+export const RQKEY = (did: string) => [RQKEY_ROOT, did]
 
 export function useProfileFollowersQuery(did: string | undefined) {
   return useInfiniteQuery<
@@ -43,7 +44,7 @@ export function* findAllProfilesInQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyGraphGetFollowers.OutputSchema>
   >({
-    queryKey: ['profile-followers'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
diff --git a/src/state/queries/profile-follows.ts b/src/state/queries/profile-follows.ts
index 428c8aebd..3abac2f10 100644
--- a/src/state/queries/profile-follows.ts
+++ b/src/state/queries/profile-follows.ts
@@ -1,19 +1,20 @@
 import {AppBskyActorDefs, AppBskyGraphGetFollows} from '@atproto/api'
 import {
-  useInfiniteQuery,
   InfiniteData,
   QueryClient,
   QueryKey,
+  useInfiniteQuery,
 } from '@tanstack/react-query'
 
-import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
+import {getAgent} from '#/state/session'
 
 const PAGE_SIZE = 30
 type RQPageParam = string | undefined
 
 // TODO refactor invalidate on mutate?
-export const RQKEY = (did: string) => ['profile-follows', did]
+const RQKEY_ROOT = 'profile-follows'
+export const RQKEY = (did: string) => [RQKEY_ROOT, did]
 
 export function useProfileFollowsQuery(did: string | undefined) {
   return useInfiniteQuery<
@@ -46,7 +47,7 @@ export function* findAllProfilesInQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyGraphGetFollows.OutputSchema>
   >({
-    queryKey: ['profile-follows'],
+    queryKey: [RQKEY_ROOT],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
diff --git a/src/state/queries/profile-lists.ts b/src/state/queries/profile-lists.ts
index 505d33b9f..9cc395e43 100644
--- a/src/state/queries/profile-lists.ts
+++ b/src/state/queries/profile-lists.ts
@@ -1,11 +1,13 @@
 import {AppBskyGraphGetLists} from '@atproto/api'
-import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
+import {InfiniteData, QueryKey, useInfiniteQuery} from '@tanstack/react-query'
+
 import {getAgent} from '#/state/session'
 
 const PAGE_SIZE = 30
 type RQPageParam = string | undefined
 
-export const RQKEY = (did: string) => ['profile-lists', did]
+const RQKEY_ROOT = 'profile-lists'
+export const RQKEY = (did: string) => [RQKEY_ROOT, did]
 
 export function useProfileListsQuery(did: string, opts?: {enabled?: boolean}) {
   const enabled = opts?.enabled !== false
diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts
index 19492cf66..2094e0c3a 100644
--- a/src/state/queries/profile.ts
+++ b/src/state/queries/profile.ts
@@ -30,10 +30,18 @@ import {RQKEY as RQKEY_MY_BLOCKED} from './my-blocked-accounts'
 import {RQKEY as RQKEY_MY_MUTED} from './my-muted-accounts'
 import {ThreadNode} from './post-thread'
 
-export const RQKEY = (did: string) => ['profile', did]
-export const profilesQueryKey = (handles: string[]) => ['profiles', handles]
+const RQKEY_ROOT = 'profile'
+export const RQKEY = (did: string) => [RQKEY_ROOT, did]
+
+const profilesQueryKeyRoot = 'profiles'
+export const profilesQueryKey = (handles: string[]) => [
+  profilesQueryKeyRoot,
+  handles,
+]
+
+const profileBasicQueryKeyRoot = 'profileBasic'
 export const profileBasicQueryKey = (didOrHandle: string) => [
-  'profileBasic',
+  profileBasicQueryKeyRoot,
   didOrHandle,
 ]
 
@@ -511,7 +519,7 @@ export function* findAllProfilesInQueryData(
 ): Generator<AppBskyActorDefs.ProfileViewDetailed, void> {
   const queryDatas =
     queryClient.getQueriesData<AppBskyActorDefs.ProfileViewDetailed>({
-      queryKey: ['profile'],
+      queryKey: [RQKEY_ROOT],
     })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData) {
diff --git a/src/state/queries/resolve-uri.ts b/src/state/queries/resolve-uri.ts
index 95fc867dd..18005cccf 100644
--- a/src/state/queries/resolve-uri.ts
+++ b/src/state/queries/resolve-uri.ts
@@ -1,11 +1,12 @@
+import {AppBskyActorDefs, AtUri} from '@atproto/api'
 import {useQuery, useQueryClient, UseQueryResult} from '@tanstack/react-query'
-import {AtUri, AppBskyActorDefs} from '@atproto/api'
 
-import {profileBasicQueryKey as RQKEY_PROFILE_BASIC} from './profile'
-import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
+import {getAgent} from '#/state/session'
+import {profileBasicQueryKey as RQKEY_PROFILE_BASIC} from './profile'
 
-export const RQKEY = (didOrHandle: string) => ['resolved-did', didOrHandle]
+const RQKEY_ROOT = 'resolved-did'
+export const RQKEY = (didOrHandle: string) => [RQKEY_ROOT, didOrHandle]
 
 type UriUseQueryResult = UseQueryResult<{did: string; uri: string}, Error>
 export function useResolveUriQuery(uri: string | undefined): UriUseQueryResult {
diff --git a/src/state/queries/search-posts.ts b/src/state/queries/search-posts.ts
index e0b317ca9..9bf3c0f9e 100644
--- a/src/state/queries/search-posts.ts
+++ b/src/state/queries/search-posts.ts
@@ -1,16 +1,17 @@
 import {AppBskyFeedDefs, AppBskyFeedSearchPosts} from '@atproto/api'
 import {
-  useInfiniteQuery,
   InfiniteData,
-  QueryKey,
   QueryClient,
+  QueryKey,
+  useInfiniteQuery,
 } from '@tanstack/react-query'
 
 import {getAgent} from '#/state/session'
 import {embedViewRecordToPostView, getEmbeddedPost} from './util'
 
+const searchPostsQueryKeyRoot = 'search-posts'
 const searchPostsQueryKey = ({query}: {query: string}) => [
-  'search-posts',
+  searchPostsQueryKeyRoot,
   query,
 ]
 
@@ -43,7 +44,7 @@ export function* findAllPostsInQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyFeedSearchPosts.OutputSchema>
   >({
-    queryKey: ['search-posts'],
+    queryKey: [searchPostsQueryKeyRoot],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
diff --git a/src/state/queries/service.ts b/src/state/queries/service.ts
index 5f7e10778..6bfd0b011 100644
--- a/src/state/queries/service.ts
+++ b/src/state/queries/service.ts
@@ -1,7 +1,8 @@
 import {BskyAgent} from '@atproto/api'
 import {useQuery} from '@tanstack/react-query'
 
-export const RQKEY = (serviceUrl: string) => ['service', serviceUrl]
+const RQKEY_ROOT = 'service'
+export const RQKEY = (serviceUrl: string) => [RQKEY_ROOT, serviceUrl]
 
 export function useServiceQuery(serviceUrl: string) {
   return useQuery({
diff --git a/src/state/queries/suggested-feeds.ts b/src/state/queries/suggested-feeds.ts
index 7e6b534ad..3be0c0b89 100644
--- a/src/state/queries/suggested-feeds.ts
+++ b/src/state/queries/suggested-feeds.ts
@@ -1,10 +1,11 @@
-import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
 import {AppBskyFeedGetSuggestedFeeds} from '@atproto/api'
+import {InfiniteData, QueryKey, useInfiniteQuery} from '@tanstack/react-query'
 
-import {getAgent} from '#/state/session'
 import {STALE} from '#/state/queries'
+import {getAgent} from '#/state/session'
 
-export const suggestedFeedsQueryKey = ['suggestedFeeds']
+const suggestedFeedsQueryKeyRoot = 'suggestedFeeds'
+export const suggestedFeedsQueryKey = [suggestedFeedsQueryKeyRoot]
 
 export function useSuggestedFeedsQuery() {
   return useInfiniteQuery<
diff --git a/src/state/queries/suggested-follows.ts b/src/state/queries/suggested-follows.ts
index 45b3ebb62..a93f935f2 100644
--- a/src/state/queries/suggested-follows.ts
+++ b/src/state/queries/suggested-follows.ts
@@ -6,21 +6,24 @@ import {
   moderateProfile,
 } from '@atproto/api'
 import {
-  useInfiniteQuery,
-  useQueryClient,
-  useQuery,
   InfiniteData,
   QueryClient,
   QueryKey,
+  useInfiniteQuery,
+  useQuery,
+  useQueryClient,
 } from '@tanstack/react-query'
 
-import {useSession, getAgent} from '#/state/session'
-import {useModerationOpts} from '#/state/queries/preferences'
 import {STALE} from '#/state/queries'
+import {useModerationOpts} from '#/state/queries/preferences'
+import {getAgent, useSession} from '#/state/session'
+
+const suggestedFollowsQueryKeyRoot = 'suggested-follows'
+const suggestedFollowsQueryKey = [suggestedFollowsQueryKeyRoot]
 
-const suggestedFollowsQueryKey = ['suggested-follows']
+const suggestedFollowsByActorQueryKeyRoot = 'suggested-follows-by-actor'
 const suggestedFollowsByActorQueryKey = (did: string) => [
-  'suggested-follows-by-actor',
+  suggestedFollowsByActorQueryKeyRoot,
   did,
 ]
 
@@ -125,7 +128,7 @@ function* findAllProfilesInSuggestedFollowsQueryData(
   const queryDatas = queryClient.getQueriesData<
     InfiniteData<AppBskyActorGetSuggestions.OutputSchema>
   >({
-    queryKey: ['suggested-follows'],
+    queryKey: [suggestedFollowsQueryKeyRoot],
   })
   for (const [_queryKey, queryData] of queryDatas) {
     if (!queryData?.pages) {
@@ -148,7 +151,7 @@ function* findAllProfilesInSuggestedFollowsByActorQueryData(
   const queryDatas =
     queryClient.getQueriesData<AppBskyGraphGetSuggestedFollowsByActor.OutputSchema>(
       {
-        queryKey: ['suggested-follows-by-actor'],
+        queryKey: [suggestedFollowsByActorQueryKeyRoot],
       },
     )
   for (const [_queryKey, queryData] of queryDatas) {