成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從源碼理清 UseEffect 第二個參數(shù)是怎么處理的

開發(fā) 前端
useEffect 第二個參數(shù)傳入 undefined、[]、[a,b,c] 時執(zhí)行的效果不同, undefined 每次都會執(zhí)行,而依賴數(shù)組只有在依賴變了才會執(zhí)行,空數(shù)組只會執(zhí)行一次。

useEffect 是常用的 hook,它支持兩個參數(shù),第一個參數(shù)是回調函數(shù),第二個參數(shù)是依賴。

當?shù)诙€參數(shù)為 null 或 undefined 的時候,回調函數(shù)每次 render 都會執(zhí)行,而參數(shù)為數(shù)組的時候,只有依賴項變了才會執(zhí)行。

這些我們都很熟悉了,但它是怎么實現(xiàn)的呢?我們來從源碼來找下答案。

useEffect 的第二個參數(shù)

我們先來試一下第二個參數(shù)傳入 undefined、空數(shù)組、有依賴的數(shù)組時的效果。

準備這樣一段代碼:

import { useEffect, useRef, useState } from 'react';

function Dong() {
const ref = useRef(1);
const [,setState] = useState();
useEffect(() => {
console.log(111);
});
useEffect(() => {
console.log(222);
}, []);
useEffect(() => {
console.log(333);
}, [ref.current]);
useEffect(() => {
setInterval(() => {
setState([]);
}, 1000);
setTimeout(() => {
ref.current = 2;
}, 3000);
}, []);
return <div>dong</div>;
}

我們用寫了三個 useEffect,第二個參數(shù)分別為 undefined、[]、有一個依賴的數(shù)組,回調函數(shù)里分別打印 111、222、333。

然后 useState 聲明了一個 state,用 setInterval 定時修改,這樣能不斷觸發(fā) render。

又用 useRef 聲明了一個對象,它的特點是每次 render 都是返回的同一個對象,我們用 setTimeout 在 2s 后修改了它的值。

執(zhí)行的結果大家應該很容易想到:

111 每次都會打印,因為第二個參數(shù)為 undefined。

222 只打印一次,因為第二個參數(shù)為 []。

333 打印兩次,因為第二個參數(shù)有一個依賴,這個依賴在 2s 的時候會變一次。

這些我們都很熟悉了,但是它為什么是這樣呢?

我們來看下源碼:

useEffect 相關源碼

react hooks 的原理前面一篇文章寫過,我們再過一遍:

jsx 編譯產生 render function,執(zhí)行返回 vdom,但是為了提高性能,React 16 引入 fiber 架構,會先把 vdom 轉成 fiber,然后再去更新到 dom。

vdom 轉 fiber 的過程叫做 reconcile,更新到 dom 的過程叫做 commit。reconcile 的過程是可打斷的,需要 schedule。

hooks 也是基于 fiber 來實現(xiàn)的,它在 fiber 節(jié)點上維護了一個鏈表(memorizedState 屬性),用來保存數(shù)據(jù),每個 hook 都是從對應的鏈表元素上存取各自的數(shù)據(jù)。

比如上面那個組件的 6 個 hook 就對應著 fiber 節(jié)點上 memorizedState 鏈表的 6 個元素:

每個 hook 都是在對應的鏈表元素上存取數(shù)據(jù)的。

這個鏈表有個建立的過程,叫做 mount,后面只需要 update,所以每個 hook 的實現(xiàn)都會分為 mount 和 update 兩個階段。

我們看下 useEffect 相關的源碼:

它也是分為了 mountEffect 和 updateEffect 兩個函數(shù),最終都是在 hook.memorizedState 存取元素的。這就是 hook 的通用原理。

第二個參數(shù)對應的就是 deps,它是怎么判斷是否要更新的呢?

我們著重看下這段邏輯:

deps 是新傳入的參數(shù),如果是 undefined 會作為 null。

hook.memorizedState.deps 取到的是之前的 deps。

然后新舊 deps 會做下對比,如果返回 true 才會執(zhí)行 effect。

對比的邏輯在 areHookInputsEqual 這個函數(shù)里:

如果 prevDeps 是 null,那就直接返回 false,這就是 useEffect 第二個參數(shù)傳 undefined 或者 null 的話 effect 函數(shù)都會執(zhí)行的原因。

否則,才會新舊的 deps 數(shù)組中每個元素做對比,有一個不一樣就返回 false。

這已經解釋了上面那個案例,deps 數(shù)組傳 undefined、[]、[dep] 時 effect 執(zhí)行的不同情況。

其實還有一種情況也會導致 effect 執(zhí)行,就是上面這段邏輯:

當熱更新的時候,就算依賴沒有變,也需要重新執(zhí)行 effect,這個是通過 ignorePreviousDependencies 變量來控制的。

這個估計很多人都不知道,因為熱更新是工具實現(xiàn)的。

我們從源碼層面解釋清楚了 useEffect 第二個參數(shù)的處理機制。

其實 useCallback、useMemo 的 deps 參數(shù)處理邏輯也是一樣的,源碼都差不多:

總結

useEffect 第二個參數(shù)傳入 undefined、[]、[a,b,c] 時執(zhí)行的效果不同, undefined 每次都會執(zhí)行,而依賴數(shù)組只有在依賴變了才會執(zhí)行,空數(shù)組只會執(zhí)行一次。

我們從源碼層面解釋了原因:

hooks 是在 fiber 節(jié)點的 memorizedState 屬性上存取數(shù)據(jù)的,會組織一個和 hook 一一對應的鏈表。

構建這個鏈表的階段叫 mount,后面只需要 update,所以所有的 hook 的實現(xiàn)都分為了 mountXxx 和 updateXxx 兩部分。

useEffect 在 update 時會對比新傳入的 deps 和之前存在 memorizedState 上的 deps 來確定是否執(zhí)行 effect 回調,它做了這樣的處理:

當 dep 是 null(undefined 也會處理成 null)時,判定為不相等。如果是熱更新的時候,判定為不相等。否則會對比數(shù)組的每個依賴項來判斷是否相等。只要新舊 deps 不相等就執(zhí)行 effect。

useCallback、useMemo 的 deps 處理也是一樣的,我們從源碼層面理清楚了 deps 參數(shù)的處理機制。

責任編輯:姜華 來源: 神光的編程秘籍
相關推薦

2023-11-26 17:59:00

React組件參數(shù)

2011-05-23 10:16:25

VMware微軟

2020-09-11 10:27:07

鴻蒙安卓操作系統(tǒng)

2009-11-05 09:54:03

盜版黨歐洲議會

2016-07-07 13:20:43

阿里云計算yunos

2011-09-21 13:09:33

HTML 5

2011-11-01 10:21:16

UbuntuAndroid

2022-05-18 10:26:21

微軟Linux穩(wěn)定版

2011-02-18 14:04:27

Ubuntu 10.0

2010-10-25 06:33:43

戴爾dell虛擬化

2009-02-09 09:13:13

Windows 7BetaUAC

2010-10-08 11:29:45

AndroidiPhone

2012-05-07 23:41:43

JavaJVMCeylon

2015-08-12 11:35:32

Windows 10Windows 8

2021-05-17 18:56:20

甲骨文云區(qū)域

2022-03-26 09:39:53

SOC運營數(shù)據(jù)

2020-11-27 18:06:36

Python 開發(fā)編程語言

2017-05-17 06:34:18

Android谷歌

2019-06-19 09:00:33

驅動器安裝Windows 10
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美激情视频一区二区三区在线播放 | 日韩区| 欧美aⅴ| 国产精品久久久久久 | 精品一区av| 91在线精品播放 | 天天搞天天操 | 国产精品亚洲一区 | 91在线视频免费观看 | 一级在线观看 | 久久一区二区免费视频 | 精久久| 亚洲www啪成人一区二区麻豆 | 久久er99热精品一区二区 | 九九综合 | 在线观看www视频 | 91丨国产| chinese中国真实乱对白 | 日韩电影免费观看中文字幕 | 国产精品自拍视频网站 | 国产精品毛片av一区 | 欧美亚洲综合久久 | 日韩国产一区二区三区 | 一区二区三区在线 | 成年人网站免费视频 | av香港经典三级级 在线 | 国产精品污www一区二区三区 | 亚洲精品毛片av | 亚洲精品女人久久久 | 成人精品毛片国产亚洲av十九禁 | 久久精品91久久久久久再现 | 奇米超碰在线 | 日韩精品 电影一区 亚洲 | 欧美一级片在线播放 | 国产精品一区免费 | 国产黄色大片在线观看 | 看a网站 | www.五月婷婷.com | 国产精品99久久久久久动医院 | 欧美精品综合 | 日韩天堂av |