React中的useEffect(副作用)介紹
useEffect(副作用)介紹
useEffect是用來使函數(shù)組件也可以進(jìn)行副作用操作的。
那么什么是副作用呢?
函數(shù)的副作用就是函數(shù)除了返回值外對外界環(huán)境造成的其它影響。
舉個例子,假如我們每次執(zhí)行一個函數(shù),該函數(shù)都會操作全局的一個變量,那么對全局變量的操作就是這個函數(shù)的副作用。而在React的世界里,我們的副作用大體可以分為兩類,一類是調(diào)用瀏覽器的API,例如使用addEventListener來添加事件監(jiān)聽函數(shù)等,另外一類是發(fā)起獲取服務(wù)器數(shù)據(jù)的請求,例如當(dāng)用戶組件掛載的時候去異步獲取用戶的信息等。
react官方的原話:
如果你熟悉 React class 的生命周期函數(shù),你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 這三個函數(shù)的組合。
- componentDidMount 組件掛載
- componentDidUpdate 組件更新
- componentWillUnmount 組件將要摧毀
語法:
import {useEffect} from "react" useEffect(() => { /** 執(zhí)行邏輯 */ }, dependencies) //dependencies是一個數(shù)組,是可選的 //或者: useEffect(effect?=>clean?, dependencies?)
useEffect的第一個參數(shù) effect 是要執(zhí)行的副作用函數(shù),它可以是任意的用戶自定義函數(shù),用戶可以在這個函數(shù)里面操作一些瀏覽器的API或者和外部環(huán)境進(jìn)行交互,網(wǎng)絡(luò)請求等,這個函數(shù)會在每次組件渲染完成之后被調(diào)用。
useEffect可以有一個返回值,返回一個函數(shù),系統(tǒng)在組件重新渲染之前調(diào)用,用于清除副作用(比如說副作用是定時器,return里面就可以寫清除定時器的代碼)。它第二個參數(shù)dependencies(依賴項)來限制該副作用的執(zhí)行條件
useEffect(副作用)各種寫法的調(diào)用時刻
1.寫法一:沒有依賴項時
useEffect所在組件每次渲染(包括首次)時都要調(diào)用:組件中任何變化都會執(zhí)行(eg:useState解構(gòu)出的state改了就會引發(fā)組件重新渲染,父組件給子組件傳遞屬性的值改變,子組件中的useEffect就會執(zhí)行)
//沒有依賴項 useEffect(()=>{ console.log('組件每次渲染時都要調(diào)用(頁面每次刷新)'); })
組件生命周期里面有一種生命周期父組件給子組件傳新的屬性就會調(diào)用的生命周期函數(shù),useEffect寫法一就可以替代。
組件自身狀態(tài)變化會調(diào)用beforeupdate和updated,useEffect寫法一就可以替代。
父組件給子組件傳值:
2.寫法二:依賴項中有監(jiān)聽的值時
根據(jù)依賴項中監(jiān)聽的變量是否變化決定是否執(zhí)行副作用,變了就執(zhí)行,不變就不執(zhí)行。
//依賴項中有值時 //頁面首次渲染和父組件給子組件傳的屬性值和子組件自身的值改變(依賴項改變才會打印) useEffect(() => { console.log('頁面首次渲染和依賴項改變的時候才會打印'); },[num,props.title])
3.寫法三:依賴項為空數(shù)組時
相當(dāng)于Vue生命周期函數(shù)mounted,也就是頁面首次渲染(掛載)后,后面不管組件中值咋改變都不會執(zhí)行了,除非該組件銷毀了再重新掛載時才會執(zhí)行。
useEffect(() => { console.log('頁面首次渲染'); },[])
4.寫法四:清除副作用寫法
(假如副作用是一個定時器,清除定時器,如果不清的話,會出現(xiàn)內(nèi)存泄漏)
useEffect(() => { let timer = setInterval(()=>{ console.log(66666); },1000) return ()=>{ //當(dāng)組件下一次渲染前,執(zhí)行這個函數(shù):清除副作用(計時器就是一種副作用) console.log('當(dāng)組件下一次渲染前,執(zhí)行這個函數(shù):清除副作用'); clearInterval(timer); } })//這里沒寫依賴項,所以頁面中的值改變就會刷新,比如useState解構(gòu)出的state改變
問題:副作用函數(shù)不會有緩存,那為什么在副作用函數(shù)useEffect里面寫了定時器,頁面(組件)刷新之后上一個定時器沒有清除?
就非要寫return 返回一個函數(shù)去清除副作用(定時器)
5.寫法五:依賴項是一個函數(shù)的時候
let fn = ()=>{ console.log(11111111); } useEffect(() => { console.log('此組件渲染時,就會運行(包括首次渲染)'); // 該組件渲染時(包括首次渲染),就會執(zhí)行副作用 let timer = setInterval(()=>{ console.log(66666); },1000) return ()=>{ //而當(dāng)該組件下一次運行(渲染)時,才會執(zhí)行清除副作用函數(shù)(第一次渲染不執(zhí)行(組件首次渲染時),下一次渲染才執(zhí)行) console.log('當(dāng)組件下一次渲染前,執(zhí)行這個函數(shù):清除副作用'); clearInterval(timer); } },[fn])
分析:當(dāng)依賴項 fn 函數(shù)運行的時候,副作用函數(shù)才會運行(先執(zhí)行副作用函數(shù)的return返回的函數(shù),把上一次渲染生成的定時器清除,才會執(zhí)行副作用函數(shù),重新生成一個定時器),但是return返回的函數(shù)不一定運行,因為return返回的函數(shù)必須要是在該組件下一次渲染時,才會執(zhí)行。因為fn函數(shù)雖然執(zhí)行,但是并沒有引起組件重新渲染,所以并不會執(zhí)行return返回的函數(shù)。
缺點是:函數(shù)組件刷新時,函數(shù)fn又會重新生成一模一樣的,沒必要,會占用內(nèi)存。有沒有一種技術(shù),在組件刷新時,這種像fn函數(shù)的,不重新生成,就用原來內(nèi)存中的fn,就不用去重新開辟內(nèi)存空間去生成函數(shù)fn。所以就用到了useCallback
注意點
1.
//這種沒依賴項 let [data,setData] = useState(''); useEffect(()=>{ //這里可以進(jìn)行請求后臺數(shù)據(jù),但是不能通過setData()將請求回來的數(shù)據(jù)把頁面刷新 //會陷入死循環(huán),頁面一刷新 useEffect就會執(zhí)行,就會請求后臺數(shù)據(jù),請求回來的數(shù)據(jù)又 //通過setData()導(dǎo)致頁面數(shù)據(jù)改變?nèi)缓笏⑿?,這樣就會陷入死循環(huán) setData(); }) //如果有依賴項的話,就不會陷入死循環(huán)
2.組件重新渲染時,會將那些非hook相關(guān)的數(shù)據(jù)重新生成一份,比如說,
let [num,setNum] = useState(100); //hook相關(guān)的數(shù)據(jù) let m = 100; //普通的數(shù)據(jù) let arr = [100,200,900];//普通的引用數(shù)據(jù) let fm = ()=>{} //普通的引用數(shù)據(jù)
以use開頭的那些hook組件刷新時不會重新生成,那些普通的數(shù)據(jù)會重新生成。
如果依賴項是這種普通的arr,fm等引用數(shù)據(jù),組件刷新時,就會重新生成,重新開辟內(nèi)存空間生成,所以就會導(dǎo)致副作用函數(shù)執(zhí)行,所以一般副作用函數(shù)的依賴項都是父組件給子組件傳的屬性或者useState解構(gòu)出的state值這些。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
React Native 混合開發(fā)多入口加載方式詳解
這篇文章主要介紹了React Native 混合開發(fā)多入口加載方式詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09關(guān)于react ant 組件 Select下拉框 值回顯的問題
這篇文章主要介紹了關(guān)于react ant 組件 Select下拉框 值回顯的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08reset.css瀏覽器默認(rèn)樣式表重置(user?agent?stylesheet)的示例代碼
這篇文章主要介紹了reset.css瀏覽器默認(rèn)樣式表重置(user?agent?stylesheet),本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-12-12