最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ReactQuery系列之數據轉換示例詳解

 更新時間:2022年11月10日 11:19:35   作者:lakb248  
這篇文章主要為大家介紹了ReactQuery系列之數據轉換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

歡迎來到“關于react-query我不得不說的一些事情”的第二章節(jié)。隨著我越來越深入這個庫以及他的社區(qū),我發(fā)現一些人們經常會問到的問題。最開始,我計劃在一篇超長的文章里面把這些都講清楚,最終我還是決定將他們拆分成一些有意義的主題。今天第一個主題是一個很普遍但是很重要的事情:數據轉換。

數據轉換

我們不得不面對這個問題-大部分的人并沒有使用GraphQL。如果你使用了,那么恭喜你,因為你可以請求到你期望的數據格式。

如果你在使用REST風格的API,你就必須受限于后端返回的數據格式。所以在使用react-query的時候我們應該在什么地方通過什么方式來進行數據轉換呢?

答案只有一個:看情況。

下面列舉出四種進行數據轉換的方式,以及他們的優(yōu)缺點:

后端

這是我最喜歡的方式,如果你有決定權的話。如果后端返回的數據結構是你所期望的話,那么你就什么都不用做了。但是在很多場景這并不太現實,比如一些公共的REST API,特別是在企業(yè)級應用中。如果你可以讓后端針對每一個具體的場景都有一個對應的接口,那么可以返回你期望的數據結構。

  • 優(yōu)點:
    前端什么都不用做
  • 缺點:
    并不是所有情況下都能做到

查詢函數中

查詢函數是你傳給useQuery的函數。他會返回一個Promise,最終返回的數據會被存在緩存中。但是這并不意味著你只能按照后端給你的數據結構來返回數據。你可以在返回之前進行數據轉換:

const fetchTodos = async (): Promise<Todos> => {
  const response = await axios.get('todos')
  const data: Todos = response.data
  return data.map((todo) => todo.name.toUpperCase())
}
export const useTodosQuery = () => useQuery(['todos'], fetchTodos)

之后你就可以在其他地方使用轉換之后的數據,仿佛后端返回的數據就是這樣的。你在其他地方都不會拿到不是大寫的todo名字了。同時你也拿不到數據的原始結構了。如果你查看react-query-devtools,你會看到轉換之后的結構。如果你查看網絡請求,你可以看到原始的數據結構。這個可能會有點讓人感到困惑,所以不要忘了你在代碼里面處理了數據結構。

同時,在這里react-query并不會做什么優(yōu)化。也就是說每一次fetch被執(zhí)行的時候,你的轉換邏輯都會被執(zhí)行。如果轉換邏輯很復雜,需要考慮一下其他轉換方式。一些公司在前端會有一個公共的API層來抽象數據獲取,所以你可能沒辦法在這個抽象層里面做你的數據轉換。

  • 優(yōu)點:
    和API調用綁定在一起,對上層無感知
  • 缺點:
    在每次數據請求的時候都會運行
    如果你有一個你無法修改的公共的API層,這個方式不太可行
  • 其他:
    存儲在緩存中的是轉換之后的數據結構,所以你沒辦法拿到原始的數據結構

render函數中

正如第一章節(jié)中介紹的,你可以自定義一個hook,那么你可以很方便的在這個hook里做數據轉換:

const fetchTodos = async (): Promise<Todos> => {
  const response = await axios.get('todos')
  return response.data
}
export const useTodosQuery = () => {
  const queryInfo = useQuery(['todos'], fetchTodos)
  return {
    ...queryInfo,
    data: queryInfo.data?.map((todo) => todo.name.toUpperCase()),
  }
}

正如代碼邏輯所示,數據轉換不會在每次數據查詢的時候運行,但是會在每次render的時候運行(即使這次render并沒有觸發(fā)數據請求)。這看起來這不是什么大問題,如果你在意的話,你可以通過useMemo來進行優(yōu)化,同時盡可能只定義真正需要的依賴列表。queryInfo中的data是引用穩(wěn)定的除非數據真的發(fā)生了變化,但是queryInfo就不是了。如果你把queryInfo作為你的依賴,那么轉換邏輯就會在每次render的時候運行:

export const useTodosQuery = () => {
  const queryInfo = useQuery(['todos'], fetchTodos)
  return {
    ...queryInfo,
    // ?? don't do this - the useMemo does nothing at all here!
    data: React.useMemo(
      () => queryInfo.data?.map((todo) => todo.name.toUpperCase()),
      [queryInfo]
    ),
    // ? correctly memoizes by queryInfo.data
    data: React.useMemo(
      () => queryInfo.data?.map((todo) => todo.name.toUpperCase()),
      [queryInfo.data]
    ),
  }
}

特別是當你在自定義hook中有一些額外的邏輯來協(xié)助進行數據轉換的時候,這是一個很好的選擇。需要注意的是data有可能是undefined,所以請使用可選鏈式訪問來獲取data中的數據。

  • 優(yōu)點:
    可以通過useMemo進行優(yōu)化
  • 缺點
    寫法有一些晦澀
    data可能會是undefined
  • 其他
    確切的數據結構無法在devtool中展示

使用select配置

v3引入了內置的selector,可以用它來進行數據轉換:

export const useTodosQuery = () =>
  useQuery(['todos'], fetchTodos, {
    select: (data) => data.map((todo) => todo.name.toUpperCase()),
  })

selector只會在data存在的時候被調用,所以你不用擔心undefiend的問題。像上面的selector會在每次render的時候被執(zhí)行,因為函數表達式變化了(因為這是一個內聯(lián)函數)。如果轉換邏輯比較復雜,你可以使用useCallback來進行memoize,或者把他抽象到一個穩(wěn)定的函數引用中:

const transformTodoNames = (data: Todos) =>
  data.map((todo) => todo.name.toUpperCase())
export const useTodosQuery = () =>
  useQuery(['todos'], fetchTodos, {
    // ? uses a stable function reference
    select: transformTodoNames,
  })
export const useTodosQuery = () =>
  useQuery(['todos'], fetchTodos, {
    // ? memoizes with useCallback
    select: React.useCallback(
      (data: Todos) => data.map((todo) => todo.name.toUpperCase()),
      []
    ),
  })

在未來,select配置也可以被用來訂閱data中的部分數據。這使得這一數據轉換實現方式變得特別??纯聪旅孢@個例子:

export const useTodosQuery = (select) =>
  useQuery(['todos'], fetchTodos, { select })
export const useTodosCount = () => useTodosQuery((data) => data.length)
export const useTodo = (id) =>
  useTodosQuery((data) => data.find((todo) => todo.id === id))

這里,我們創(chuàng)建了一個像useSelector一樣的API,你可以傳自定義selector到useTodosQuery中。這個自定義hook仍然可以像之前一樣工作,如果你沒有傳select,會返回整個數據。
但是如果你傳了selector,你就只會訂閱selector返回的部分數據。這是很有用的,因為這意味著如果我們更新了一個todo的名字,只通過useTodosCount訂閱了count的組件并不會重新渲染。count沒有發(fā)生變化,所以react-query可以選擇不通知這部分數據的訂閱者(注意這里說得很容易,但是具體實現不完全跟這個描述一樣,我會在第三部分渲染優(yōu)化中聊一聊這部分內容)

  • 優(yōu)點:
    最佳優(yōu)化
    支持部分訂閱
  • 其他:
    每個訂閱者的數據可能都不一樣

以上就是ReactQuery系列之數據轉換示例詳解的詳細內容,更多關于ReactQuery 數據轉換的資料請關注腳本之家其它相關文章!

相關文章

  • React useImperativeHandle處理組件狀態(tài)和生命周期用法詳解

    React useImperativeHandle處理組件狀態(tài)和生命周期用法詳解

    React Hooks 為我們提供了一種全新的方式來處理組件的狀態(tài)和生命周期,useImperativeHandle是一個相對較少被提及的Hook,但在某些場景下,它是非常有用的,本文將深討useImperativeHandle的用法,并通過實例來加深理解
    2023-09-09
  • 解決react中l(wèi)abel標簽for報錯問題

    解決react中l(wèi)abel標簽for報錯問題

    這篇文章主要介紹了react中l(wèi)abel標簽for報錯問題,解決辦法就是react中l(wèi)abel標簽沒有for屬性,用htmlFor代替for屬性,感興趣的朋友跟隨小編一起看看吧
    2022-02-02
  • 用React Native制作一個簡單的游戲引擎

    用React Native制作一個簡單的游戲引擎

    今天給大家分享的是使用React Native制作一個簡單的游戲,這個游戲可以跨平臺操作,本文通過實例圖文相結合給大家介紹的非常詳細,對React Native游戲相關知識感興趣的朋友一起看看吧
    2021-05-05
  • 使用react實現手機號的數據同步顯示功能的示例代碼

    使用react實現手機號的數據同步顯示功能的示例代碼

    本篇文章主要介紹了使用react實現手機號的數據同步顯示功能的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 一文帶你了解React中的并發(fā)機制

    一文帶你了解React中的并發(fā)機制

    React 18.2.0 引入了一系列并發(fā)機制的新特性,旨在幫助各位開發(fā)者更好地控制和優(yōu)化應用程序的性能和用戶體驗,下面我們就來看看如何利用這些新特性構建更高效、更響應式的應用程序吧
    2024-03-03
  • React之echarts-for-react源碼解讀

    React之echarts-for-react源碼解讀

    這篇文章主要介紹了React之echarts-for-react源碼解讀,echarts-for-react的源碼非常精簡,本文將針對主要邏輯分析介紹,需要的朋友可以參考下
    2022-10-10
  • react使用websocket實時通信方式

    react使用websocket實時通信方式

    這篇文章主要介紹了react使用websocket實時通信方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • React中useRef的具體使用

    React中useRef的具體使用

    這篇文章主要介紹了React中useRef的具體使用,它可以用來獲取組件實例對象或者是DOM對象,除此之外還有哪些用法,就一起來了解一下
    2021-04-04
  • 詳解React-Todos入門例子

    詳解React-Todos入門例子

    本篇文章主要介紹了React-Todos入門例子,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • 淺談React Native Flexbox布局(小結)

    淺談React Native Flexbox布局(小結)

    這篇文章主要介紹了淺談React Native Flexbox布局(小結),小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01

最新評論

綦江县| 稷山县| 铜陵市| 乌鲁木齐市| 密云县| 龙山县| 泾源县| 巴彦淖尔市| 唐河县| 合川市| 旺苍县| 田阳县| 福泉市| 延长县| 华坪县| 得荣县| 遂平县| 南汇区| 徐汇区| 焉耆| 马边| 澳门| 通江县| 花莲县| 永清县| 顺义区| 康乐县| 监利县| 武乡县| 祁门县| 前郭尔| 随州市| 奉贤区| 石阡县| 肃宁县| 谷城县| 饶阳县| 三亚市| 军事| 汉川市| 海淀区|