React useEffect的理解與使用
React16.8新增的useEffec這個(gè)hook函數(shù)就是處理副作用的。
所謂的“副作用”,舉個(gè)通俗一點(diǎn)的例子,假如感冒了本來(lái)吃點(diǎn)藥就沒(méi)事了,但是吃了藥發(fā)現(xiàn)身體過(guò)敏了,而這個(gè)“過(guò)敏”就是副作用。
放到React中,本來(lái)只是想渲染DOM展示到頁(yè)面上,但除了DOM之外還有數(shù)據(jù),而這些數(shù)據(jù)必須從外部的數(shù)據(jù)源中獲取,這個(gè)“獲取外部數(shù)據(jù)源”的過(guò)程就是副作用。
useEffect怎么用可以參考官網(wǎng)給出的例子,這里主要針對(duì)使用useEffect過(guò)程中遇到的問(wèn)題進(jìn)行總結(jié)。
避免重復(fù)循環(huán)渲染
利用useEffect接收一個(gè)數(shù)組作為第二個(gè)參數(shù),將第二個(gè)參數(shù)作為dependence,每次渲染完DOM執(zhí)行副作用函數(shù)時(shí)都會(huì)淺比較dependence渲染前后的值是否一致,不一致就執(zhí)行副作用,反之就不執(zhí)行;如果該dependence為一個(gè)空數(shù)組[],即沒(méi)有傳入比較變化的變量,則比較結(jié)果永遠(yuǎn)都保持不變,那么副作用邏輯就只能執(zhí)行一次。
useEffect(() => { setTimeout(() => { setCounter(counter + 1); }, 300) }, []);
初此之外,如果我們還想通過(guò)點(diǎn)擊刷新按鈕實(shí)現(xiàn)獲取外部數(shù)據(jù)但又不想造成死循環(huán),那么可以通過(guò)一個(gè)變量作為“開(kāi)關(guān)”,在實(shí)現(xiàn)目的的同時(shí)做到避免循環(huán)渲染DOM。
畫(huà)動(dòng)圖太麻煩,各位看注釋腦補(bǔ)😂
function App() { const [count, setCount] = useState(0); const [loading, setLoading] = useState(true); // loading作為開(kāi)關(guān) useEffect(() => { if (loading) { // 注意這里只有當(dāng)loading為true時(shí)才執(zhí)行 setTimeout(() => { setCount(count + 1); setLoading(!loading); // 改變loading值 }); } }, [loading]); // loading在這里作為dependence // 第一次DOM渲染完成后,loading為true,執(zhí)行副作用函數(shù),count值變?yōu)?,loading變?yōu)閒alse,由于 // 改變了state的值,會(huì)update,組件會(huì)再次render,但此時(shí)loading為false,不會(huì)執(zhí)行setTimeout, // 避免了循環(huán) // 當(dāng)點(diǎn)擊Refresh刷新,loading由上一次的false變?yōu)榱藅rue,函數(shù)執(zhí)行一次update // DOM更新完后執(zhí)行useEffect,因?yàn)閘oading已經(jīng)為true了,所以副作用函數(shù)可執(zhí)行,count從1變?yōu)?, // loading又從true變?yōu)閒alse,就這樣交替進(jìn)行。。。 return ( <div> <h3>{count}</h3> <button onClick={() => { setLoading(true); }} > Refresh </button> </div> );}
關(guān)于副作用的清除
useEffect可以返回一個(gè)函數(shù)來(lái)作為清除副作用。
useEffect(() => { ChatAPI.subscribeToFriendStatus(props.id, handleStatusChange); function clear(){ ChatAPI.unsubscribeFromFriendStatus(props.id, handleStatusChange); } return clear; });
這里會(huì)涉及到useEffect執(zhí)行和銷(xiāo)毀的過(guò)程:
- 傳入props.id = 1
- 組件渲染
- DOM渲染完成,執(zhí)行副作用函數(shù),返回清除副作用函數(shù)clear,命名為clear1
- 傳入props.id=2
- 組件渲染
- DOM渲染完成,執(zhí)行clear1
- 副作用函數(shù)執(zhí)行并返回另一個(gè)clear函數(shù),命名為clear2
- 組件銷(xiāo)毀,clear2執(zhí)行
由此可推測(cè)出副作用清除函數(shù)的特征:
- 每次副作用執(zhí)行都會(huì)返回一個(gè)清除函數(shù)
- 清除函數(shù)會(huì)在下一次副作用函數(shù)執(zhí)行之前(DOM渲染完成之后)執(zhí)行
- 組件銷(xiāo)毀也會(huì)執(zhí)行一次清除函數(shù)
從打印出的count值也可以看出,清除函數(shù)會(huì)在下一次副作用函數(shù)執(zhí)行之前執(zhí)行,即在清除函數(shù)里的count值是上一次緩存的count值:
進(jìn)一步思考,clear1執(zhí)行的時(shí)候,訪問(wèn)了props.id,那么這個(gè)id值是1還是2呢?
這里就涉及到閉包的知識(shí)概念了,因?yàn)閡seEffect返回的是個(gè)函數(shù),在執(zhí)行時(shí)產(chǎn)生了一個(gè)閉包,根據(jù)閉包的相關(guān)定義,返回的clear函數(shù)能訪問(wèn)自身作用域外的變量,當(dāng)組件第一次渲染時(shí)傳入id=1,此時(shí)的clear函數(shù)中的props.id值為1。
以上就是React useEffect的理解與使用的詳細(xì)內(nèi)容,更多關(guān)于React useEffect的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React跨端動(dòng)態(tài)化之從JS引擎到RN落地詳解
這篇文章主要為大家介紹了React跨端動(dòng)態(tài)化之從JS引擎到RN落地,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09使用react在修改state中的數(shù)組和對(duì)象數(shù)據(jù)的時(shí)候(setState)
這篇文章主要介紹了使用react在修改state中的數(shù)組和對(duì)象數(shù)據(jù)的時(shí)候(setState),具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09react中useEffect函數(shù)的詳細(xì)用法(最新推薦)
useEffect是React中的一個(gè)Hook,用于在函數(shù)組件中處理副作用(如數(shù)據(jù)獲取、訂閱、手動(dòng)更改 DOM 等),useEffect屬于組件的生命周期方法,下面通過(guò)本文給大家分享react中useEffect函數(shù)的詳細(xì)用法,感興趣的朋友跟隨小編一起看看吧2024-06-06JavaScript的React Web庫(kù)的理念剖析及基礎(chǔ)上手指南
這篇文章主要介紹了JavaScript的React Web庫(kù)的理念剖析及基礎(chǔ)上手指南,React Web的目的即是把本地的React Native應(yīng)用程序項(xiàng)目變?yōu)閃eb應(yīng)用程序,需要的朋友可以參考下2016-05-05React ts模式使用http-proxy-middleware代理時(shí)訪問(wèn)報(bào)404問(wèn)題
這篇文章主要介紹了React ts模式使用http-proxy-middleware代理時(shí)訪問(wèn)報(bào)404問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07React?component.forceUpdate()強(qiáng)制重新渲染方式
這篇文章主要介紹了React?component.forceUpdate()強(qiáng)制重新渲染方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10解析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