詳解React組件卸載怎么中止遞歸方法
問(wèn)題的出現(xiàn)——組件卸載怎么中止遞歸方法
朋友在處理彈幕相關(guān)業(yè)務(wù)的時(shí)候,出現(xiàn)了一個(gè)bug:組件中的方法在組件卸載后仍然在執(zhí)行。代碼片段發(fā)給我看,但是變量的用意我也不懂,只看到有方法調(diào)用自身方法,這不就是遞歸嘛(最后發(fā)現(xiàn)是定時(shí)器沒(méi)有清除的問(wèn)題)??。
遞歸的中止這還不簡(jiǎn)單,在方法中添加一個(gè)中止條件不就好了。
const Children = () => {
const [isStop, setStop] = useState(false)
// 遞歸
const recursion = async (num: number) => {
if (isStop) return
console.log(num)
await sleep(1000)
recursion(num + 1)
}
useEffect(() => {
recursion(1)
return () => {
setStop(() => true)
}
}, [])
return (
<div>Children</div>
)
}
const HomePage: React.FC = () => {
const [flag, setFlag] = useState(false)
return (
<div>
<Button onClick={() => setFlag(!flag)}>點(diǎn)擊</Button>
{
flag && <Children></Children>
}
</div>
);
};

結(jié)果與預(yù)期好像不太一樣,突然仔細(xì)想一下,當(dāng)組件卸載時(shí),所有與該組件相關(guān)的狀態(tài)(通過(guò)useState定義的狀態(tài))都會(huì)被清除,這怎么可能會(huì)有效呢!
簡(jiǎn)單閉包處理
既然狀態(tài)在組件卸載的時(shí)候被清理了,那么在遞歸內(nèi)部增加狀態(tài)來(lái)控制遞歸不就行了。閉包就很適合現(xiàn)在的場(chǎng)景。
const controller = () => {
// 遞歸的狀態(tài)(開(kāi)始/結(jié)束)
let state = false
// 遞歸方法
const recursion = async (num: number) => {
// 結(jié)束條件
if (state === false) return
console.log(num)
await sleep(1000)
recursion(num + 1)
}
return {
// 開(kāi)啟遞歸
start: (num: number) => {
state = true
recursion(num)
},
// 結(jié)束遞歸
close: () => state = false
}
}
我們?cè)趻燧d結(jié)束后創(chuàng)建一個(gè)單一實(shí)例用來(lái)控制遞歸方法,并在卸載的時(shí)候?qū)⑦f歸的狀態(tài)改為false即可。如果需要在組件的其他位置使用,還是使用useRef對(duì)實(shí)例進(jìn)行包裹比較好。
useEffect(() => {
let c = controller()
c.start(1)
return () => {
c.close()
}
}, [])

Hook useRef處理
const Children = () => {
const isUnmounted = useRef(false);
// 遞歸
const recursion = async (num: number) => {
if (isUnmounted.current) return
console.log(num)
await sleep(1000)
recursion(num + 1)
}
useEffect(() => {
recursion(1)
return () => {
isUnmounted.current = true
}
}, [])
return (
<div>Children</div>
)
}
const HomePage: React.FC = () => {
const [flag, setFlag] = useState(false)
return (
<div>
<Button onClick={() => setFlag(!flag)}>點(diǎn)擊</Button>
{
flag && <Children></Children>
}
</div>
);
};
來(lái)自CHAT-GPT
這是因?yàn)?code>useRef創(chuàng)建的引用對(duì)象是在組件的閉包中存在的,而不是作為組件的狀態(tài)存在。所以即使組件卸載,引用對(duì)象仍然可以被訪(fǎng)問(wèn)和修改。
個(gè)人理解,useRef創(chuàng)建的引用對(duì)象在遞歸方法中被引用,類(lèi)似閉包的原理,所以在組件卸載的時(shí)候沒(méi)有被清理。(如果理解錯(cuò)誤,歡迎指正,輕點(diǎn)噴??)
用途
我覺(jué)得在頁(yè)面請(qǐng)求完數(shù)據(jù)之后,需要對(duì)數(shù)據(jù)進(jìn)行復(fù)雜遞歸處理的時(shí)候,又把頁(yè)面關(guān)閉,這種情況可能需要。
到此這篇關(guān)于詳解React組件卸載怎么中止遞歸方法的文章就介紹到這了,更多相關(guān)React中止遞歸方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react使用antd的上傳組件實(shí)現(xiàn)文件表單一起提交功能(完整代碼)
最近在做一個(gè)后臺(tái)管理項(xiàng)目,涉及到react相關(guān)知識(shí),項(xiàng)目需求需要在表單中帶附件提交,怎么實(shí)現(xiàn)這個(gè)功能呢?下面小編給大家?guī)?lái)了react使用antd的上傳組件實(shí)現(xiàn)文件表單一起提交功能,一起看看吧2021-06-06
React Native可定制底板組件Magic Sheet使用示例
這篇文章主要為大家介紹了React Native可定制的底板組件Magic Sheet使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
React項(xiàng)目build打包頁(yè)面空白的解決方案
React項(xiàng)目執(zhí)行build命令后,在本地服務(wù)器打開(kāi)頁(yè)面是空白的,本文主要介紹了React項(xiàng)目build打包頁(yè)面空白的解決方案,感興趣的可以了解一下2023-08-08
如何使用React的VideoPlayer構(gòu)建視頻播放器
本文介紹了如何使用React構(gòu)建一個(gè)基礎(chǔ)的視頻播放器組件,并探討了常見(jiàn)問(wèn)題和易錯(cuò)點(diǎn),通過(guò)組件化思想和合理管理狀態(tài),可以實(shí)現(xiàn)功能豐富且性能優(yōu)化的視頻播放器2025-01-01
教你快速搭建 React Native 開(kāi)發(fā)環(huán)境
這篇文章主要介紹了搭建 React Native 開(kāi)發(fā)環(huán)境的詳細(xì)過(guò)程,本文通過(guò)圖文指令給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
React?Native系列之Recyclerlistview使用詳解
這篇文章主要為大家介紹了React?Native系列之Recyclerlistview使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
react-router-domV6版本的路由和嵌套路由寫(xiě)法詳解
本文主要介紹了react-router-domV6版本的路由和嵌套路由寫(xiě)法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考
下面小編就為大家?guī)?lái)一篇基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05

