React Query 小記

配圖源自 Freepik

原文鏈接

本文以 V5 版本為例

Query Key

它是由字符串、(可嵌套)對(duì)象、或兩者兼具組成的數(shù)組。

順序

數(shù)組的順序很重要

// 以下 Query Key 不相同
useQuery({ queryKey: ['todos', status, page] })
useQuery({ queryKey: ['todos', page, status] })
useQuery({ queryKey: ['todos', undefined, page, status] })

對(duì)象的順序不重要

// 以下 Query Key 相同
useQuery({ queryKey: ['todos', { status, page }] })
useQuery({ queryKey: ['todos', { page, status }] })
useQuery({ queryKey: ['todos', { page, status, other: undefined }] })

對(duì)象總是以確定性的 sort 排序:??

/**
 * Default query & mutation keys hash function.
 * Hashes the value into a stable hash.
 */
export function hashKey(queryKey: QueryKey | MutationKey): string {
  return JSON.stringify(queryKey, (_, val) =>
    isPlainObject(val)
      ? Object.keys(val)
          .sort()
          .reduce((result, key) => {
            result[key] = val[key]
            return result
          }, {} as any)
      : val,
  )
}

結(jié)構(gòu)化

盡管 Query Key 在整個(gè) Query 中唯一便可使用,但我們可以按一定的顆粒度進(jìn)行劃分。比如:

useQuery({ queryKey: ['todos', 'list', { filters: 'all' }] })
useQuery({ queryKey: ['todos', 'list', { filters: 'done' }] })
useQuery({ queryKey: ['todos', 'detail', 1] })
useQuery({ queryKey: ['todos', 'detail', 2] })

這樣做的好處是,在處理數(shù)據(jù)更新時(shí)更加靈活,或者批量使對(duì)應(yīng)緩存失效:

function useUpdateTitle() {
  return useMutation({
    mutationFn: updateTitle,
    onSuccess: newTodo => {
      // 更新單個(gè)數(shù)據(jù)
      queryClient.setQueryData(['todos', 'detail', newTodo.id], newTodo)

      // 更新列表數(shù)據(jù)
      queryClient.setQueriesData(['todos', 'list'], previous =>
        previous.map(todo => (todo.id === newTodo.id ? newTodo : todo))
      )

      // 使查詢列表失效
      queryClient.invalidateQueries({queryKey: ['todos', 'list']})
    },
  })
}

Related link: https://tkdodo.eu/blog/effective-react-query-keys#structure

有時(shí),使用“純對(duì)象”的 Query Key 更好:

function useTodosQuery(filter: string) {
  return useQuery({
    // queryKey: ["todos", "list", filter],
    queryKey: [{scope: 'todos', entity: 'list', filter}],
    queryFn: ({queryKey}) => {
      // 保不準(zhǔn)下次會(huì)新增什么參數(shù),此時(shí)對(duì)象要優(yōu)于數(shù)組
      // const [, , filter] = queryKey;
      const {filter} = queryKey
      return fetchTodos({filter})
    },
  })
}

Related Link: https://tkdodo.eu/blog/leveraging-the-query-function-context#object-query-keys

Select

在 useQuery 或 useInfinityQuery 中的 select 會(huì)在每次組件更新時(shí)執(zhí)行,而不是查詢結(jié)果變化時(shí)才執(zhí)行,所以按需使用 useCallback(但如果處理不會(huì)很復(fù)雜,也不需要緩存處理)。

References

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容