官术网_书友最值得收藏!

1.3.3 useEffect

useEffect是除useState之外另一個常用的Hooks,理解它比理解useState的難度更大,但只要明白函數(shù)組件每次渲染都有它自己的狀態(tài)和props,那么理解useEffect將變得容易。

useEffect能讓開發(fā)人員知道DOM什么時候被繪制到了屏幕上,組件什么時候被卸載了。有些開發(fā)人員認為useEffect是類組件componentDidMount、componentDidUpdate和componentWillUnmount的生命周期函數(shù)的結(jié)合,但實際上函數(shù)組件沒有與類組件類似的生命周期概念。useEffect類型定義如下。

從類型定義可以看出,useEffect最多可接收兩個參數(shù)。第一個參數(shù)是函數(shù),可以有返回值,本小節(jié)將該函數(shù)稱為effect;第二個參數(shù)是非必填的,是一個數(shù)組,它是effect的依賴,稱為deps。deps用于確定effect在本次渲染中是否應(yīng)該執(zhí)行,若應(yīng)該執(zhí)行,則在瀏覽器中將DOM繪制到屏幕之后執(zhí)行,可以將Ajax請求、訪問DOM等操作放在effect中,它不會阻塞瀏覽器繪制。

函數(shù)組件可以多次使用useEffect,每使用一次就定義一個effect,這些effect的執(zhí)行順序與它們被定義的順序一致,建議將不同職責的代碼放在不同的effect中。接下來從effect的清理工作和依賴這兩個方面介紹useEffect。

1.effect的清理工作

effect沒有清理工作就意味著它沒有返回值,相關(guān)代碼如下。

上述代碼定義了一個effect,它的作用是將document.title設(shè)置成本次渲染時name的值。

effect的清理工作由effect返回的函數(shù)完成,該函數(shù)在組件重新渲染后和組件卸載時調(diào)用。代碼清單1-2定義了一個有清理工作的effect。

代碼清單 1-2

上述effect在DOM被繪制到界面之后給body元素綁定click事件,組件重新渲染之后將上一次effect綁定的click事件解綁。該effect在組件首次渲染和之后的每次重新渲染時都會執(zhí)行,如果組件的狀態(tài)更新頻繁,那么組件重新渲染也會很頻繁,這將導致body頻繁綁定click事件又解綁click事件。是否有辦法使組件只在首次渲染時給body綁定事件呢?當然有,那就是依賴。

2.effect的依賴

前面兩個示例定義的effect沒有指明依賴,因此組件的每一輪渲染都會執(zhí)行它們。修改代碼清單1-2,讓組件只在首次渲染時給body綁定事件,實現(xiàn)代碼如下。

給useEffect的第二個參數(shù)傳空數(shù)據(jù)意味著effect沒有依賴,該effect只在組件初始渲染時執(zhí)行,它的清理工作在組件卸載時執(zhí)行。對于綁定DOM事件而言這是一件好事,它可以防止事件反復(fù)綁定和解綁,但問題是,如果在事件處理程序中訪問組件的狀態(tài)和props,那么只能拿到它們的初始值,拿不到最新的值。是否有辦法讓effect始終拿到狀態(tài)和props最新的值呢?有。

給effect傳遞依賴項,React會將本次渲染時依賴項的值與上一次渲染時依賴項的值進行淺對比,如果它們當中的一個有變化,那么該effect會被執(zhí)行,否則不會執(zhí)行。為了讓effect拿到它所需狀態(tài)和props的最新值,effect中所有要訪問的外部變量都應(yīng)該作為依賴項放在useEffect的第二個參數(shù)中。相關(guān)代碼如下。

上述effect在組件初始渲染時會執(zhí)行,當name發(fā)生變化導致組件重新渲染時也會執(zhí)行,相應(yīng)地,組件卸載時和由name的變化導致組件重新渲染之后將清理上一個effect。

注意

函數(shù)組件每次渲染時,effect都是一個不同的函數(shù),在函數(shù)組件內(nèi)的每一個位置(包括事件處理函數(shù)、effects、定時器等)只能拿到定義它們的那次渲染的狀態(tài)和props。

主站蜘蛛池模板: 安顺市| 肃宁县| 临颍县| 青州市| 普格县| 满城县| 阿拉善左旗| 宁蒗| 静安区| 南岸区| 临夏市| 万荣县| 长泰县| 寿光市| 普兰店市| 乌兰察布市| 泗洪县| 上栗县| 库车县| 定日县| 奉新县| 镇康县| 马关县| 开封县| 军事| 攀枝花市| 盐亭县| 云霄县| 江口县| 法库县| 邢台市| 蒲江县| 高邮市| 昂仁县| 额尔古纳市| 客服| 出国| 保山市| 东乡县| 盐边县| 彝良县|