關(guān)于useEffect執(zhí)行兩次的問(wèn)題及解決
useEffect執(zhí)行兩次問(wèn)題
在useEffect第二個(gè)參數(shù)變化的時(shí)候,需要在父組件里面更改這個(gè)值的地方加一個(gè)判斷,如果有值則設(shè)置為空,else更新這個(gè)值。useEffect第二個(gè)值可以是表達(dá)式
父組件里面
//授權(quán)樹(shù)展示 ? ? const handleRoleModalVisible = (RoleModelVisibel: boolean, record?: any) => { ? ? ? ? setRoleModalVisible(RoleModelVisibel); ? ? ? ? // console.log(record) ? ? ? ? if(RoleModelVisibel==undefined){ ? ? ? ? ? ? setroleAuth(undefined) ? ? ? ? }else{ ? ? ? ? ? ? setroleAuth(record) ? ? ? ? } ? ? };
子組件里面
?const {roleAuth, treeData, roleModalVisible, handleRoleModalVisible} = props; ? ? useEffect(() => { ? ? ? ? queryTreeId({role_id: roleAuth.roleId}).then(res => { ? ? ? ? ? ? setCheckedKeys(res.data.content) ? ? ? ? ? ? setSelectedKeys(res.data.content) ? ? ? ? }) ? ? }, [roleAuth!==undefined])
在最后
?{ ? ? ?roleAuth&&<Authority roleAuth={roleAuth} ?treeData={treeData} ? ? ?roleModalVisible={roleModalVisible} handleRoleModalVisible={handleRoleModalVisible}/> ?}
react使用useEffect及踩坑
useEffect 介紹
useEffect時(shí)reactHook中最重要,最常用的hook之一。
useEffect相當(dāng)于react中的什么生命周期呢?
這個(gè)問(wèn)題在react官網(wǎng)中有過(guò)介紹,在使用的過(guò)程中,容易被忽略,在面試的時(shí)候卻經(jīng)常被問(wèn)及,(面試造航母,上班擰螺絲?),開(kāi)個(gè)玩笑這個(gè)問(wèn)題并不難回答,下面是react官方的原話:
如果你熟悉 React class 的生命周期函數(shù),你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 這三個(gè)函數(shù)的組合。
componentDidMount
組件掛載componentDidUpdate
組件更新componentWillUnmount
組件將要摧毀
useEffect需要傳遞兩個(gè)參數(shù),第一個(gè)參數(shù)是邏輯處理函數(shù),第二個(gè)參數(shù)是一個(gè)數(shù)組
用法
useEffect(() => { /** 執(zhí)行邏輯 */ },[])
重要理解
一、第二個(gè)參數(shù)存放變量,當(dāng)數(shù)組存放變量發(fā)生改變時(shí),第一個(gè)參數(shù),邏輯處理函數(shù)將會(huì)被執(zhí)行
二、第二個(gè)參數(shù)可以不傳,不會(huì)報(bào)錯(cuò),但瀏覽器會(huì)無(wú)線循環(huán)執(zhí)行邏輯處理函數(shù)。
useEffect(() => { /** 執(zhí)行邏輯 */ })
三、第二個(gè)參數(shù)如果只傳一個(gè)空數(shù)組,邏輯處理函數(shù)里面的邏輯只會(huì)在組件掛載時(shí)執(zhí)行一次 ,不就是相當(dāng)于 componentDidMount
useEffect(() => { /** 執(zhí)行邏輯 */ },[])
四、第二個(gè)參數(shù)如果不為空數(shù)組,如下
const [a, setA] = useState(1); const [b, setB] = useState(2); useEffect(() => { /** 執(zhí)行邏輯 */ },[a,b])
邏輯處理函數(shù)會(huì)在組件掛載時(shí)執(zhí)行一次和(a或者b變量在棧中的值發(fā)生改變時(shí)執(zhí)行一次) 這是不是相當(dāng)于componentDidMount 和 componentDidUpdate 的結(jié)合
五、useEffect第一個(gè)參數(shù)可以返回一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)將會(huì)在組件被摧毀之前和再一次觸發(fā)更新時(shí),將之前的副作用清除掉。這就相當(dāng)于componentWillUnmount。
useEffect去除副作用。我們可能會(huì)在組件即將被掛載的時(shí)候創(chuàng)建一些不斷循環(huán)的訂閱(計(jì)時(shí)器,或者遞歸循環(huán))。在組件被摧毀之前,或者依賴數(shù)組的元素更新后,應(yīng)該將這些訂閱也給摧毀掉。
比如以下的情況(沒(méi)有去除計(jì)時(shí)器,增大不必要的開(kāi)銷和代碼風(fēng)險(xiǎn))
const [time, setTime] = useState(0) useEffect(() => { ?? ?const InterVal = setInterval(() => { ?? ??? ?setTime(time + 1) ?? ?},1000) },[])
利用第五點(diǎn),在組件被摧毀前去除計(jì)時(shí)器。
const [time, setTime] = useState(0) useEffect(() => { ?? ?const InterVal = setInterval(() => { ?? ??? ?setTime(time + 1) ?? ?},1000) ?? ?return () => { ? ??? ??? ?clearInterval(InterVal ) ? ??? ?} },[])
useEffect常見(jiàn)跳坑
1、useEffect執(zhí)行函數(shù)被循環(huán)執(zhí)行。
出現(xiàn)這種情況可能有兩種原因。
沒(méi)傳第二個(gè)參數(shù)
useEffect(() => { /** 執(zhí)行邏輯 */ })
2、你在useEffect執(zhí)行函數(shù)里面改變了useEffect監(jiān)測(cè)的變量
const [a, setA] = useState(1); useEffect(() => { /** 執(zhí)行邏輯 */ setA(a + 1) },[a])
解決的方法 不要在useEffect第一參數(shù)執(zhí)行函數(shù)中去改變第二參數(shù)依賴元素的地址的值。當(dāng)依賴元素的地址的值發(fā)生改變,又會(huì)執(zhí)行一次執(zhí)行函數(shù),這不是無(wú)限循環(huán)么。
3、useEffect監(jiān)測(cè)不到依賴數(shù)組元素的變化。
只有一種可能,依賴數(shù)組元素的地址的值根本就沒(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])
是因?yàn)閏hangeA沒(méi)有真正的改變a在棧中的值(地址的值),只是改變了a在堆中的值。
useEffect監(jiān)測(cè)不到堆中值得變化,所有引用類型數(shù)據(jù)都應(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])
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
react中value與defaultValue的區(qū)別及說(shuō)明
這篇文章主要介紹了react中value與defaultValue的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05React?Native性能優(yōu)化紅寶書(shū)方案詳解
React?Native?是Facebook在React.js?Conf2015推出的開(kāi)源框架,使用React和應(yīng)用平臺(tái)的原生功能來(lái)構(gòu)建Android和iOS應(yīng)用,這篇文章主要介紹了React?Native性能優(yōu)化紅寶書(shū),需要的朋友可以參考下2024-06-06聊聊ant?design?charts?獲取后端接口數(shù)據(jù)展示問(wèn)題
今天在做項(xiàng)目的時(shí)候遇到幾個(gè)讓我很頭疼的問(wèn)題,一個(gè)是通過(guò)后端接口成功訪問(wèn)并又返回?cái)?shù)據(jù),但拿不到數(shù)據(jù)值。其二是直接修改state中的data,console中數(shù)組發(fā)生變化但任然數(shù)據(jù)未顯示,這篇文章主要介紹了ant?design?charts?獲取后端接口數(shù)據(jù)展示,需要的朋友可以參考下2022-05-0530分鐘精通React今年最勁爆的新特性——React Hooks
這篇文章主要介紹了30分鐘精通React今年最勁爆的新特性——React Hooks,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03webpack入門(mén)+react環(huán)境配置
webpack是一個(gè)前端資源模塊化管理和打包工具,說(shuō)白了就是方便我們管理自己的常用的一些代碼,比如你開(kāi)發(fā)中用到sass以及jade同時(shí)用到es6,開(kāi)發(fā)時(shí)你不可能改動(dòng)某個(gè)地方就挨個(gè)命令去轉(zhuǎn)換再到瀏覽器去看效果,那樣效率是非常低的。所以webpack幫我們省去了那些多余的步驟。2017-02-02Zustand介紹與使用 React狀態(tài)管理工具的解決方案
本文主要介紹了Zustand,一種基于React的狀態(tài)管理庫(kù),Zustand以簡(jiǎn)潔易用、靈活性高及最小化原則等特點(diǎn)脫穎而出,旨在提供簡(jiǎn)單而強(qiáng)大的狀態(tài)管理功能2024-10-10react使用websocket實(shí)時(shí)通信方式
這篇文章主要介紹了react使用websocket實(shí)時(shí)通信方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09