日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React18中請求數據的官方姿勢適用其他框架_React

作者:魔術師卡頌 ? 更新時間: 2022-09-04 編程語言

引言

一些同學喜歡在useEffect中請求初始數據,類似這樣:

useEffect(() => {
  fetch(xxx).then(data => setState(data.json()))
}, [])

React18并不推薦這種方式。

這么寫有什么問題?如果不推薦這種方式,那么推薦的方式是什么呢?

本文來看看Dan在reddit是如何回答上述問題的。

這是一個普遍的問題

除了React外,大部分以組件形式組織的前端框架,都有如下類似的API

effect

didMount/didUpdate

如果有初始化時請求數據的需求,這類框架都會選擇在上述回調函數內執行請求操作,并在數據返回后更新狀態。

所以,這并不是React獨有的問題。相反,他很普遍。

之所以在React中這么突出,是因為React官方在引導開發者不要用這種形式書寫代碼(通過嚴格模式下useEffect執行兩次放大這個問題)。

React之所以這么做,是為了項目的性能以及UX(User Experience,用戶體驗)。

下面我們來細聊這么做的影響。注意,這些影響同樣適用于其他框架。

為什么不推薦這么寫?

需要解決競態問題

useEffect中請求數據要面臨的第一個問題是需要解決競態問題

假設你有個組件User,接收userID作為props,用userID請求數據后展示用戶信息。

下面是你的寫法:

function User({userID}) {
  const [data, setData] = useState(null);
  useEffect(() => {
    const res = await fetch(`https://xxx/${userID}/`);
    setData(res.json());
  }, [userID]);
  if (data) {
    return <div>{data.name}</div>;
  } 
  return null;
}

這里有個開發階段很難復現的bug —— 如果userID變化足夠快,會發起多個不同的用戶請求。

而最終展示哪個用戶的數據,取決于哪個請求先返回。這就是請求的競態問題

點擊返回按鈕后重新請求數據

如果用戶跳轉到新的頁面后,又通過瀏覽器回退按鈕回到當前頁面,并不能立刻看到他跳轉前的頁面。

相反,看到的可能是個白屏 —— 因為還需要重新執行useEffect獲取初始數據。

這個問題的本質原因是:沒有初始數據的緩存。

CSR時的白屏時間

CSR(Client-Side Rendering,客戶端渲染)時在useEffect中請求數據,在數據返回前頁面都是白屏狀態。

瀑布問題

如果父子組件都依賴useEffect獲取初始數據渲染,那么整個渲染流程如下:

  • 父組件mount
  • 父組件useEffect執行,請求數據
  • 數據返回后重新渲染父組件
  • 子組件mount
  • 子組件useEffect執行,請求數據
  • 數據返回后重新渲染子組件

可見,當父組件數據請求成功后子組件甚至還沒開始首屏渲染。

這就是渲染中的瀑布問題 —— 數據像瀑布一樣一級一級向下流動,流到的組件才開始渲染,很低效。

既然直接寫useEffect有這么多問題,那么推薦的方式是什么呢?

推薦的方式

Meta公司內部,基于Relay驅動數據(但請求數據要求使用GraphQL),所以這套架構比較難在社區普及開。

但是,現在社區已經有了成熟的請求數據的方案

對于SSR,可以使用Next.jsRemix接管數據請求。

對于CSR,可以使用React QueryuseSWR接管數據請求。

這些成熟的方案都致力于解決上述提到的問題。

如果不想使用這些方案,想自己寫,可以參考React新文檔中下面兩篇文章:

使用effect同步數據

你可能不需要使用effect

想看中文的同學,可以看我寫的總結 —— React新文檔:不要濫用effect哦

總結

本文我們聊了React18之后不推薦的請求數據的方式以及推薦的請求數據的方式。

其中不推薦的請求數據的方式不僅存在于React中,很多前端框架都有這樣的問題。

原文鏈接:https://juejin.cn/post/7115595794425577502

欄目分類
最近更新