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

ReactQuery?渲染優(yōu)化示例詳解

 更新時(shí)間:2022年11月10日 11:16:25   作者:lakb248  
這篇文章主要為大家介紹了ReactQuery?渲染優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

免責(zé)聲明:渲染優(yōu)化是所有應(yīng)用的進(jìn)階話題。React Query已經(jīng)進(jìn)行了許多性能優(yōu)化并且開箱即用,大多數(shù)時(shí)候不需要做更多優(yōu)化。"不必要的重新渲染"是一個(gè)很多人投入大量關(guān)注的話題,也是我要寫這篇文章的原因。但是我要再一次指出,大部分情況下對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō),渲染優(yōu)化很可能并沒有想得那么重要。重新渲染是一個(gè)好事情。它保證了你的應(yīng)用展示了最新的狀態(tài)。相比于重復(fù)渲染,我更關(guān)注由于缺少渲染而導(dǎo)致的渲染錯(cuò)誤。對(duì)于更多關(guān)于這個(gè)話題的討論,可以看下面的內(nèi)容:

我在第二篇文章介紹select的內(nèi)容中已經(jīng)講了一些關(guān)于渲染優(yōu)化的事情。然而,"為什么在沒有任何數(shù)據(jù)變化的情況下,React Query會(huì)渲染兩次組件呢"是我平時(shí)被問(wèn)到最多的一個(gè)問(wèn)題。我們讓我來(lái)嘗試深入解釋一下。

isFetching

在之前的例子中我說(shuō)過(guò),下面這個(gè)組件只會(huì)在todos的length變化時(shí)才會(huì)重新渲染,其實(shí)我只說(shuō)了一部分事實(shí):

export const useTodosQuery = (select) =>
  useQuery(['todos'], fetchTodos, { select })
export const useTodosCount = () => useTodosQuery((data) => data.length)
function TodosCount() {
  const todosCount = useTodosCount()
  return <div>{todosCount.data}</div>
}

每次發(fā)生后臺(tái)refetch的時(shí)候,這個(gè)組件都會(huì)下面的數(shù)據(jù)分別進(jìn)行一次渲染:

{ status: 'success', data: 2, isFetching: true }
{ status: 'success', data: 2, isFetching: false }

這是因?yàn)镽eact Query在每個(gè)查詢中返回了很多基本信息,isFetching就是其中一個(gè)。這個(gè)屬性在請(qǐng)求正在發(fā)生的時(shí)候會(huì)被設(shè)置為true。這個(gè)在你想要展示一個(gè)后臺(tái)請(qǐng)求的loading標(biāo)志的時(shí)候特別有用。但是如果你不需要,那確實(shí)會(huì)造成一些不必要的渲染。

notifiOnChange

對(duì)于上面說(shuō)到的這個(gè)場(chǎng)景,React Query提供了notifyOnChangeProps參數(shù)。他可以在每個(gè)場(chǎng)景單獨(dú)設(shè)置來(lái)告訴React Query:只在這些屬性發(fā)生變化的時(shí)候再通知我。通過(guò)將這個(gè)參數(shù)設(shè)置為['data'],我們可以實(shí)現(xiàn)一個(gè)新的版本:

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

保持同步

盡管上面的代碼可以正常工作,但是它很容易就會(huì)造成不同步。如果我們希望針對(duì)error進(jìn)行特殊處理呢?又或者我們需要使用isLoading屬性呢?我們不得不確保notifyOnChangeProps屬性和我們實(shí)際用到的數(shù)據(jù)保持同步。如果我們忘記將某個(gè)數(shù)據(jù)添加到屬性里面,而只監(jiān)聽data屬性的變化,當(dāng)查詢返回錯(cuò)誤,同時(shí)我們也要展示這些錯(cuò)誤的時(shí)候,我們的組件并不會(huì)重新渲染。這個(gè)問(wèn)題當(dāng)我們把這些屬性寫死在自定義hook的時(shí)候格外明顯,因?yàn)槲覀儾⒉恢朗褂米远xhook的組件實(shí)際上會(huì)用到哪些數(shù)據(jù):

export const useTodosCount = () =>
  useTodosQuery((data) => data.length, ['data'])
function TodosCount() {
  // ?? we are using error, but we are not getting notified if error changes!
  const { error, data } = useTodosCount()
  return (
    <div>
      {error ? error : null}
      {data ? data : null}
    </div>
  )
}

就像我在文章開頭免責(zé)聲明中說(shuō)的,我認(rèn)為這是比偶爾發(fā)生的不必要的重新渲染更壞的事情。當(dāng)然,我們可以傳參數(shù)給自定義hook,但是這還是需要手動(dòng)處理,是否有什么方式可以自動(dòng)處理這個(gè)情況呢?請(qǐng)看:

被追蹤的查詢

這是我感受特別自豪的一個(gè)特性,這也是我對(duì)這個(gè)庫(kù)第一個(gè)重大的貢獻(xiàn)。如果你將notifyOnChangeProps設(shè)置為'tracked',React Query會(huì)跟蹤你在渲染過(guò)程中用到的數(shù)據(jù),會(huì)自動(dòng)計(jì)算依賴列表。最終的效果就跟你手動(dòng)維護(hù)這個(gè)列表一樣,除了你不用再去關(guān)注這個(gè)問(wèn)題以外。你也可以全局開啟這個(gè)特性:

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      notifyOnChangeProps: 'tracked',
    },
  },
})
function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Example />
    </QueryClientProvider>
  )
}

利用這個(gè)特性,你再也不用考慮重新渲染。當(dāng)然這個(gè)特性也有一些限制,這就是為什么這個(gè)特性是一個(gè)可選項(xiàng):

如果你使用對(duì)象剩余屬性結(jié)構(gòu)的語(yǔ)法的話,最終所有屬性都會(huì)被追蹤。正常的解構(gòu)語(yǔ)法是沒問(wèn)題的,不要這么做:

// ?? will track all fields
const { isLoading, ...queryInfo } = useQuery(...)
// ? this is totally fine
const { isLoading, data } = useQuery(...)

被追蹤的查詢只會(huì)追蹤render過(guò)程中用到的數(shù)據(jù)。如果你只在effects中用到了這些數(shù)據(jù),他們并不會(huì)被追蹤。

const queryInfo = useQuery(...)
// ?? will not corectly track data
React.useEffect(() => {
  console.log(queryInfo.data)
})
// ? fine because the dependency array is accessed during render
React.useEffect(() => {
  console.log(queryInfo.data)
}, [queryInfo.data])

被追蹤的查詢不會(huì)在每次render的時(shí)候被重置,所以只要你使用了一次某個(gè)數(shù)據(jù),你就會(huì)在整個(gè)組件的生命周期內(nèi)追蹤這個(gè)數(shù)據(jù):

const queryInfo = useQuery(...)
if (someCondition()) {
  // ?? we will track the data field if someCondition was true in any previous render cycle
  return <div>{queryInfo.data}</div>
}

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

一個(gè)不同的但是并沒那么重要的React Query默認(rèn)開啟的渲染優(yōu)化是結(jié)構(gòu)化共享。這個(gè)特性確保數(shù)據(jù)在所有地方是引用唯一的。舉個(gè)例子,假設(shè)我們有下面這個(gè)數(shù)據(jù)結(jié)構(gòu):

[
{ "id": 1, "name": "Learn React", "status": "active" },
{ "id": 2, "name": "Learn React Query", "status": "todo" }
]

現(xiàn)在假設(shè)我們將第一個(gè)todo轉(zhuǎn)為done,然后進(jìn)行了一次后臺(tái)refetch。我們會(huì)從后端拿到一個(gè)全新的json:

{ "id": 1, "name": "Learn React", "status": "active" },
{ "id": 1, "name": "Learn React", "status": "done" },
{ "id": 2, "name": "Learn React Query", "status": "todo" }
]

現(xiàn)在React Query會(huì)嘗試對(duì)比新老狀態(tài),盡可能多的復(fù)用老的狀態(tài)。在上面的例子中,todo數(shù)據(jù)會(huì)是一個(gè)新的對(duì)象,因?yàn)槲覀兏铝艘粋€(gè)todo。第一個(gè)id為1的對(duì)象也會(huì)是新的對(duì)象,但是對(duì)于id為2的對(duì)象我們會(huì)保持跟對(duì)應(yīng)的舊數(shù)據(jù)一樣的引用-React Query會(huì)將他復(fù)制一份同樣的引用到新的數(shù)據(jù),因?yàn)檫@部分?jǐn)?shù)據(jù)并沒有發(fā)生變化。

這使得使用selector進(jìn)行部分訂閱變得特別友好:

// ? will only re-render if something within todo with id:2 changes
// thanks to structural sharing
const { data } = useTodo(2)

就像我之前提到的,對(duì)于selector來(lái)說(shuō)結(jié)構(gòu)化共享會(huì)用到兩次:一次是在queryFn返回的結(jié)果上,另一次是在selector返回的結(jié)果上。在一些場(chǎng)景,特別是數(shù)據(jù)量比較大的場(chǎng)景,結(jié)構(gòu)化共享會(huì)成為一個(gè)瓶頸。同時(shí)它只能使用在JSON可序列化的數(shù)據(jù)上。如果你不需要這個(gè)優(yōu)化,你可以通過(guò)將`structuralSharing`設(shè)為false來(lái)關(guān)閉這個(gè)特性。

以上就是ReactQuery 渲染優(yōu)化示例詳解的詳細(xì)內(nèi)容,更多關(guān)于ReactQuery 渲染優(yōu)化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • react實(shí)現(xiàn)自定義拖拽hook

    react實(shí)現(xiàn)自定義拖拽hook

    這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)自定義拖拽hook,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • React降級(jí)配置及Ant Design配置詳解

    React降級(jí)配置及Ant Design配置詳解

    這篇文章主要介紹了React降級(jí)配置及Ant Design配置詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • React中事件綁定this指向三種方法的實(shí)現(xiàn)

    React中事件綁定this指向三種方法的實(shí)現(xiàn)

    這篇文章主要介紹了React中事件綁定this指向三種方法的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • React中的生命周期用法詳解

    React中的生命周期用法詳解

    這篇文章主要介紹了React中的生命周期用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 解析React?ref?命令代替父子組件的數(shù)據(jù)傳遞問(wèn)題

    解析React?ref?命令代替父子組件的數(shù)據(jù)傳遞問(wèn)題

    這篇文章主要介紹了React?-?ref?命令為什么代替父子組件的數(shù)據(jù)傳遞,使用?ref?之后,我們不需要再進(jìn)行頻繁的父子傳遞了,子組件也可以有自己的私有狀態(tài)并且不會(huì)影響信息的正常需求,這是為什么呢?因?yàn)槲覀兪褂昧?ref?命令的話,ref是可以進(jìn)行狀態(tài)的傳輸
    2022-08-08
  • React中useState的使用方法及注意事項(xiàng)

    React中useState的使用方法及注意事項(xiàng)

    useState通過(guò)在函數(shù)組件里調(diào)用它來(lái)給組件添加一些內(nèi)部state,下面這篇文章主要給大家介紹了關(guān)于React中useState的使用方法及注意事項(xiàng)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • 基于React實(shí)現(xiàn)無(wú)限滾動(dòng)表格

    基于React實(shí)現(xiàn)無(wú)限滾動(dòng)表格

    以文本為例,為了實(shí)現(xiàn)無(wú)限循環(huán)的視覺效果,我們需要準(zhǔn)備兩段相同的文本,并讓第二段文本的頭部銜接在第一段文本的尾部,同時(shí),為兩段文本設(shè)置相同的滾動(dòng)動(dòng)畫,本文給大家介紹了基于React實(shí)現(xiàn)無(wú)限滾動(dòng)表格,需要的朋友可以參考下
    2023-11-11
  • React中使用Workbox進(jìn)行預(yù)緩存的實(shí)現(xiàn)代碼

    React中使用Workbox進(jìn)行預(yù)緩存的實(shí)現(xiàn)代碼

    Workbox是Google Chrome團(tuán)隊(duì)推出的一套 PWA 的解決方案,這套解決方案當(dāng)中包含了核心庫(kù)和構(gòu)建工具,因此我們可以利用Workbox實(shí)現(xiàn)Service Worker的快速開發(fā),本文小編給大家介紹了React中使用Workbox進(jìn)行預(yù)緩存的實(shí)現(xiàn),需要的朋友可以參考下
    2023-11-11
  • React Hooks之useRef獲取元素示例詳解

    React Hooks之useRef獲取元素示例詳解

    這篇文章主要介紹了React Hooks之useRef獲取元素示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • React Native實(shí)現(xiàn)地址挑選器功能

    React Native實(shí)現(xiàn)地址挑選器功能

    這篇文章主要為大家詳細(xì)介紹了React Native仿地址挑選器功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評(píng)論

炎陵县| 蒲江县| 南康市| 大名县| 泰安市| 乐平市| 安泽县| 咸阳市| 开化县| 都江堰市| 宁国市| 梁山县| 晋中市| 苍梧县| 云安县| 清水县| 青铜峡市| 瑞安市| 从江县| 墨竹工卡县| 高邑县| 周宁县| 顺平县| 阿瓦提县| 山丹县| 浮梁县| 唐河县| 东方市| 海晏县| 马边| 西盟| 林芝县| 商河县| 白沙| 辛集市| 彭山县| 福海县| 喀什市| 大关县| 湖北省| 达孜县|