首先我來說下在useEffect中請(qǐng)求初始數(shù)據(jù),如下所示:
useEffect(() => { fetch(xxx).then(data => setState(data.json())) }, [])
這種方式到了React18并不適用。
那如果這種方法不行,要推薦的又是那種方式?
本文來看看Dan在reddit是如何回答上述問題的。
這是一個(gè)普遍的問題
除了React外,大部分以組件形式組織的前端框架,都有如下類似的API:
effect
didMount/didUpdate
當(dāng)在初始化時(shí)請(qǐng)求數(shù)據(jù)的需求,框架基本上執(zhí)行的都是回調(diào)函數(shù)內(nèi)請(qǐng)求操作,并在數(shù)據(jù)返回后更新狀態(tài)。
但就有這么一個(gè)特立獨(dú)行,就是React。相反,他很普遍。
React“獨(dú)特”,是因?yàn)镽eact官方在引導(dǎo)開發(fā)者不要用這種形式書寫代碼(通過嚴(yán)格模式下useEffect執(zhí)行兩次放大這個(gè)問題)。
而React之這樣做,是為了項(xiàng)目的性能以及UX(User Experience,用戶體驗(yàn))。
現(xiàn)在來說說影響。注意,這些影響同樣適用于其他框架。
但這樣寫為什么不被推薦?
需要解決競態(tài)問題
在useEffect中請(qǐng)求數(shù)據(jù)要面臨的第一個(gè)問題是需要解決競態(tài)問題。
假設(shè)你有個(gè)組件User,接收userID作為props,用userID請(qǐng)求數(shù)據(jù)后展示用戶信息。
下面是你的寫法:
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; }
現(xiàn)在注意點(diǎn)就是開發(fā)階段很難復(fù)現(xiàn)的bug—— 假如userID變化足夠快,會(huì)發(fā)起多個(gè)不同的用戶請(qǐng)求。
這也決定最終展示哪個(gè)用戶的數(shù)據(jù),取決于哪個(gè)請(qǐng)求先返回。這就是請(qǐng)求的競態(tài)問題。
點(diǎn)擊返回按鈕后重新請(qǐng)求數(shù)據(jù)
假設(shè)用戶跳轉(zhuǎn)到新的頁面后,之后又通過瀏覽器回退按鈕回到當(dāng)前頁面,因此并不能立刻看到他跳轉(zhuǎn)前的頁面。
反之,看到的可能是個(gè)白屏 —— 因?yàn)檫€需要重新執(zhí)行useEffect獲取初始數(shù)據(jù)。
這個(gè)問題的本質(zhì)原因是:沒有初始數(shù)據(jù)的緩存。
CSR時(shí)的白屏?xí)r間
CSR(Client-Side Rendering,客戶端渲染)時(shí)在useEffect中請(qǐng)求數(shù)據(jù),在數(shù)據(jù)返回前頁面都是白屏狀態(tài)。
瀑布問題
在父子組件都依賴useEffect獲取初始數(shù)據(jù)渲染,這樣影響整個(gè)渲染流程如下:
父組件mount
父組件useEffect執(zhí)行,請(qǐng)求數(shù)據(jù)
數(shù)據(jù)返回后重新渲染父組件
子組件mount
子組件useEffect執(zhí)行,請(qǐng)求數(shù)據(jù)
數(shù)據(jù)返回后重新渲染子組件
可見,當(dāng)父組件數(shù)據(jù)請(qǐng)求成功后子組件甚至還沒開始首屏渲染。
這就是渲染中的瀑布問題 —— 數(shù)據(jù)像瀑布一樣一級(jí)一級(jí)向下流動(dòng),流到的組件才開始渲染,很低效。
useEffect的問題很多,那么有什么適用的好方式?
好的方式
在Meta公司內(nèi)部,基于Relay驅(qū)動(dòng)數(shù)據(jù)(但請(qǐng)求數(shù)據(jù)要求使用GraphQL),所以這套架構(gòu)比較難在社區(qū)普及開。
但是,現(xiàn)在社區(qū)已經(jīng)有了成熟的請(qǐng)求數(shù)據(jù)的方案。
對(duì)于SSR,可以使用Next.js、Remix接管數(shù)據(jù)請(qǐng)求。
對(duì)于CSR,可以使用React Query、useSWR接管數(shù)據(jù)請(qǐng)求。
上述解決方案都是十分成熟,當(dāng)然如果你有其他解決方案,建議參考React新文檔中下面兩篇文章:
使用effect同步數(shù)據(jù)
你可能不需要使用effect
注意,中文可以看的總結(jié),記住在React新文檔:不要濫用effect哦
最后,總結(jié)下其實(shí)React18之后不推薦的請(qǐng)求數(shù)據(jù)的方式以及推薦的請(qǐng)求數(shù)據(jù)的方式。其中不推薦的請(qǐng)求數(shù)據(jù)的方式這個(gè)現(xiàn)象不僅存在于React中,其他很多框架也都會(huì)出現(xiàn)這樣問題。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/128099.html
摘要:特別是開發(fā)一些只做國內(nèi)市場(chǎng),只有中文的項(xiàng)目時(shí),可能就直接被忽視了。應(yīng)用場(chǎng)景的使用場(chǎng)景基本就是根據(jù)不同國家和語言,進(jìn)行不同的顯示。比如中解析時(shí),可以同時(shí)處理兩種格式。一組為,一組為。對(duì)于中文,英文,日文都有一個(gè)默認(rèn)的匹配。 摘要 Locale是日常開發(fā)中比較容易忽視的技術(shù)點(diǎn)。特別是開發(fā)一些只做國內(nèi)市場(chǎng),只有中文的項(xiàng)目時(shí),Locale可能就直接被忽視了。而且在項(xiàng)目提出多語言支持的時(shí)候,因?yàn)?..
摘要:特別是開發(fā)一些只做國內(nèi)市場(chǎng),只有中文的項(xiàng)目時(shí),可能就直接被忽視了。應(yīng)用場(chǎng)景的使用場(chǎng)景基本就是根據(jù)不同國家和語言,進(jìn)行不同的顯示。比如中解析時(shí),可以同時(shí)處理兩種格式。一組為,一組為。對(duì)于中文,英文,日文都有一個(gè)默認(rèn)的匹配。 摘要 Locale是日常開發(fā)中比較容易忽視的技術(shù)點(diǎn)。特別是開發(fā)一些只做國內(nèi)市場(chǎng),只有中文的項(xiàng)目時(shí),Locale可能就直接被忽視了。而且在項(xiàng)目提出多語言支持的時(shí)候,因?yàn)?..
摘要:沒有耐心閱讀的同學(xué),可以直接前往學(xué)習(xí)全棧最后一公里。我下面會(huì)羅列一些,我自己錄制過的一些項(xiàng)目,或者其他的我覺得可以按照這個(gè)路線繼續(xù)深入學(xué)習(xí)的項(xiàng)目資源。 showImg(https://segmentfault.com/img/bVMlke?w=833&h=410); 本文技術(shù)軟文,閱讀需謹(jǐn)慎,長約 7000 字,通讀需 5 分鐘 大家好,我是 Scott,本文通過提供給大家學(xué)習(xí)的方法,...
摘要:多端統(tǒng)一開發(fā)框架優(yōu)秀學(xué)習(xí)資源匯總官方資源項(xiàng)目倉庫官方文檔項(xiàng)目倉庫官方文檔微信小程序官方文檔百度智能小程序官方文檔支付寶小程序官方文檔字節(jié)跳動(dòng)小程序官方文檔文章教程不敢閱讀包源碼帶你揭秘背后的哲學(xué)從到構(gòu)建適配不同端微信小程序等的應(yīng)用小程序最 Awesome Taro 多端統(tǒng)一開發(fā)框架 Taro 優(yōu)秀學(xué)習(xí)資源匯總 showImg(https://segmentfault.com/img/r...
閱讀 566·2023-03-27 18:33
閱讀 755·2023-03-26 17:27
閱讀 656·2023-03-26 17:14
閱讀 608·2023-03-17 21:13
閱讀 541·2023-03-17 08:28
閱讀 1829·2023-02-27 22:32
閱讀 1324·2023-02-27 22:27
閱讀 2207·2023-01-20 08:28