日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

關于useEffect執行兩次的問題及解決_React

作者:小兔子乖乖_C ? 更新時間: 2022-11-06 編程語言

useEffect執行兩次問題

在useEffect第二個參數變化的時候,需要在父組件里面更改這個值的地方加一個判斷,如果有值則設置為空,else更新這個值。useEffect第二個值可以是表達式

父組件里面?

//授權樹展示
? ? 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時reactHook中最重要,最常用的hook之一。

useEffect相當于react中的什么生命周期呢?

這個問題在react官網中有過介紹,在使用的過程中,容易被忽略,在面試的時候卻經常被問及,(面試造航母,上班擰螺絲?),開個玩笑這個問題并不難回答,下面是react官方的原話:

如果你熟悉 React class 的生命周期函數,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 這三個函數的組合。

  • componentDidMount 組件掛載
  • componentDidUpdate 組件更新
  • componentWillUnmount 組件將要摧毀

useEffect需要傳遞兩個參數,第一個參數是邏輯處理函數,第二個參數是一個數組

用法

useEffect(() => {
/** 執行邏輯 */
},[])

重要理解

一、第二個參數存放變量,當數組存放變量發生改變時,第一個參數,邏輯處理函數將會被執行

二、第二個參數可以不傳,不會報錯,但瀏覽器會無線循環執行邏輯處理函數。

useEffect(() => {
/** 執行邏輯 */
})

三、第二個參數如果只傳一個空數組,邏輯處理函數里面的邏輯只會在組件掛載時執行一次 ,不就是相當于 componentDidMount

useEffect(() => {
/** 執行邏輯 */
},[])

四、第二個參數如果不為空數組,如下

const [a, setA] = useState(1);
const [b, setB] = useState(2);
useEffect(() => {
/** 執行邏輯 */
},[a,b])

邏輯處理函數會在組件掛載時執行一次和(a或者b變量在棧中的值發生改變時執行一次) 這是不是相當于componentDidMount 和 componentDidUpdate 的結合

五、useEffect第一個參數可以返回一個回調函數,這個回調函數將會在組件被摧毀之前和再一次觸發更新時,將之前的副作用清除掉。這就相當于componentWillUnmount。

useEffect去除副作用。我們可能會在組件即將被掛載的時候創建一些不斷循環的訂閱(計時器,或者遞歸循環)。在組件被摧毀之前,或者依賴數組的元素更新后,應該將這些訂閱也給摧毀掉。

比如以下的情況(沒有去除計時器,增大不必要的開銷和代碼風險)?

const [time, setTime] = useState(0)
useEffect(() => {
?? ?const InterVal = setInterval(() => {
?? ??? ?setTime(time + 1)
?? ?},1000)
},[])

利用第五點,在組件被摧毀前去除計時器。

const [time, setTime] = useState(0)
useEffect(() => {
?? ?const InterVal = setInterval(() => {
?? ??? ?setTime(time + 1)
?? ?},1000)
?? ?return () => {
? ??? ??? ?clearInterval(InterVal )
? ??? ?}
},[])

useEffect常見跳坑

1、useEffect執行函數被循環執行。

出現這種情況可能有兩種原因。

沒傳第二個參數

useEffect(() => {
/** 執行邏輯 */
})

2、你在useEffect執行函數里面改變了useEffect監測的變量

const [a, setA] = useState(1);
useEffect(() => {
/** 執行邏輯 */
setA(a + 1)
},[a])

解決的方法 不要在useEffect第一參數執行函數中去改變第二參數依賴元素的地址的值。當依賴元素的地址的值發生改變,又會執行一次執行函數,這不是無限循環么。

3、useEffect監測不到依賴數組元素的變化。

只有一種可能,依賴數組元素的地址的值根本就沒變,比如:

const [a, setA] = useState({
b: 'dx',
c: '18',
})
const changeA = () => {
?? ?setA((old) => {
?? ?old.b = 'yx'
?? ?return old
?? ?})
}
useEffect(() => {
/** 當組件掛載時執行一次changeA */
changeA ()
},[])
/**當changeA執行卻沒有打印 a*/
useEffect(() => {
/** 執行邏輯 */
console.log(a)
},[a])

是因為changeA沒有真正的改變a在棧中的值(地址的值),只是改變了a在堆中的值。

useEffect監測不到堆中值得變化,所有引用類型數據都應該注意這一點。

解決的辦法:

const [a, setA] = useState({
b: 'dx',
c: '18',
})
const changeA = () => {
?? ?setA((old) => {
?? ?const newA = {...old}
?? ?newA .b = 'yx'
?? ?return newA?
?? ?})
}
useEffect(() => {
/** 當組件掛載時執行一次changeA */
changeA ()
},[])
/**當changeA執行打印 ?{b:'yx',c:'18'} ?*/
useEffect(() => {
/** 執行邏輯 */
console.log(a)
},[a])

原文鏈接:https://blog.csdn.net/weixin_47769562/article/details/121222531

欄目分類
最近更新