一. 作用
useEffect相當(dāng)于 componentDidMount(組件掛載),componentDidUpdate(組件更新) 和 componentWillUnmount(組件將要銷毀) 這三個(gè)生命周期函數(shù)的組合。
二.用法
useEffect有兩個(gè)參數(shù),第一個(gè)參數(shù)是一個(gè)回調(diào)函數(shù),第二個(gè)參數(shù)是一個(gè)數(shù)組,這個(gè)數(shù)組中的元素都是依賴,每當(dāng)依賴發(fā)生改變,就會(huì)觸發(fā)第一個(gè)函數(shù)的執(zhí)行。
三.重要理解
1.第二個(gè)參數(shù)存放變量,當(dāng)數(shù)組存放變量發(fā)生改變時(shí),第一個(gè)參數(shù),邏輯處理函數(shù)將會(huì)被執(zhí)行
2.第二個(gè)參數(shù)如果不傳,會(huì)導(dǎo)致邏輯處理函數(shù)無(wú)線循環(huán)調(diào)用
3.第二個(gè)參數(shù)如果傳遞為一個(gè)空數(shù)組,那么邏輯處理函數(shù)就只能執(zhí)行一次,相當(dāng)于componentDidMount(組件掛載)
4.如果第二個(gè)參數(shù)不是空數(shù)組,那么在數(shù)組中的依賴變化的時(shí)候就會(huì)觸發(fā)邏輯函數(shù)的調(diào)用,就像componentDidMount和componentDidUpdate組合的生命周期函數(shù)一樣
5.useEffect在組件被銷毀去除之前也會(huì)調(diào)用邏輯執(zhí)行函數(shù),會(huì)消除副作用,類似componentWillUnmount生命周期函數(shù)
四.常見(jiàn)BUG
1.邏輯執(zhí)行函數(shù)循環(huán)執(zhí)行
沒(méi)有傳遞第二個(gè)參數(shù):如果沒(méi)有傳遞第二個(gè)參數(shù)會(huì)導(dǎo)致回調(diào)函數(shù)的死循環(huán)執(zhí)行
在回調(diào)邏輯函數(shù)中修改依賴:如果在回調(diào)邏輯函數(shù)中修改依賴就會(huì)導(dǎo)致邏輯函數(shù)的不斷觸發(fā),從而造成死循環(huán)
2.useEffect監(jiān)測(cè)不到依賴的變化
依賴地址的值并沒(méi)有改變:
const [a, setA] = useState({
b: 'dx',
c: '18',
})
const changeA = () => {
setA((old) => {
old.b = 'yx'
return old
})
}
useEffect(() => {
/** 當(dāng)組件掛載時(shí)執(zhí)行一次changeA */
changeA ()
},[])
/**當(dāng)changeA執(zhí)行卻沒(méi)有打印 a*/
useEffect(() => {
/** 執(zhí)行邏輯 */
console.log(a)
},[a])
以上代碼僅僅改變的只是變量a在堆中的值,并沒(méi)有改變a在棧中地址值,useEffect無(wú)法監(jiān)測(cè)到堆中的數(shù)據(jù)變化,所以不會(huì)觸發(fā)邏輯執(zhí)行,所有的引用類型都應(yīng)該注意這一點(diǎn)
const [a, setA] = useState({
b: 'dx',
c: '18',
})
const changeA = () => {
setA((old) => {
const newA = {...old}
newA .b = 'yx'
return newA
})
}
useEffect(() => {
/** 當(dāng)組件掛載時(shí)執(zhí)行一次changeA */
changeA ()
},[])
/**當(dāng)changeA執(zhí)行打印 {b:'yx',c:'18'} */
useEffect(() => {
/** 執(zhí)行邏輯 */
console.log(a)
},[a])
像上面這樣就可以實(shí)現(xiàn)useEffect的邏輯執(zhí)行了,newA返回的是一個(gè)新的地址。