詳解React組件卸載怎么中止遞歸方法
問題的出現(xiàn)——組件卸載怎么中止遞歸方法
朋友在處理彈幕相關(guān)業(yè)務(wù)的時候,出現(xiàn)了一個bug:組件中的方法在組件卸載后仍然在執(zhí)行。代碼片段發(fā)給我看,但是變量的用意我也不懂,只看到有方法調(diào)用自身方法,這不就是遞歸嘛(最后發(fā)現(xiàn)是定時器沒有清除的問題)??。
遞歸的中止這還不簡單,在方法中添加一個中止條件不就好了。
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)組件卸載時,所有與該組件相關(guān)的狀態(tài)(通過useState
定義的狀態(tài))都會被清除,這怎么可能會有效呢!
簡單閉包處理
既然狀態(tài)在組件卸載的時候被清理了,那么在遞歸內(nèi)部增加狀態(tài)來控制遞歸不就行了。閉包就很適合現(xiàn)在的場景。
const controller = () => { // 遞歸的狀態(tà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 { // 開啟遞歸 start: (num: number) => { state = true recursion(num) }, // 結(jié)束遞歸 close: () => state = false } }
我們在掛載結(jié)束后創(chuàng)建一個單一實(shí)例用來控制遞歸方法,并在卸載的時候?qū)⑦f歸的狀態(tài)改為false
即可。如果需要在組件的其他位置使用,還是使用useRef
對實(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> ); };
來自CHAT-GPT
這是因?yàn)?code>useRef創(chuàng)建的引用對象是在組件的閉包中存在的,而不是作為組件的狀態(tài)存在。所以即使組件卸載,引用對象仍然可以被訪問和修改。
個人理解,useRef
創(chuàng)建的引用對象在遞歸方法中被引用,類似閉包的原理,所以在組件卸載的時候沒有被清理。(如果理解錯誤,歡迎指正,輕點(diǎn)噴??)
用途
我覺得在頁面請求完數(shù)據(jù)之后,需要對數(shù)據(jù)進(jìn)行復(fù)雜遞歸處理的時候,又把頁面關(guān)閉,這種情況可能需要。
到此這篇關(guān)于詳解React組件卸載怎么中止遞歸方法的文章就介紹到這了,更多相關(guān)React中止遞歸方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react使用antd的上傳組件實(shí)現(xiàn)文件表單一起提交功能(完整代碼)
最近在做一個后臺管理項(xiàng)目,涉及到react相關(guān)知識,項(xiàng)目需求需要在表單中帶附件提交,怎么實(shí)現(xiàn)這個功能呢?下面小編給大家?guī)砹藃eact使用antd的上傳組件實(shí)現(xiàn)文件表單一起提交功能,一起看看吧2021-06-06React Native可定制底板組件Magic Sheet使用示例
這篇文章主要為大家介紹了React Native可定制的底板組件Magic Sheet使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10React項(xiàng)目build打包頁面空白的解決方案
React項(xiàng)目執(zhí)行build命令后,在本地服務(wù)器打開頁面是空白的,本文主要介紹了React項(xiàng)目build打包頁面空白的解決方案,感興趣的可以了解一下2023-08-08如何使用React的VideoPlayer構(gòu)建視頻播放器
本文介紹了如何使用React構(gòu)建一個基礎(chǔ)的視頻播放器組件,并探討了常見問題和易錯點(diǎn),通過組件化思想和合理管理狀態(tài),可以實(shí)現(xiàn)功能豐富且性能優(yōu)化的視頻播放器2025-01-01教你快速搭建 React Native 開發(fā)環(huán)境
這篇文章主要介紹了搭建 React Native 開發(fā)環(huán)境的詳細(xì)過程,本文通過圖文指令給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08React?Native系列之Recyclerlistview使用詳解
這篇文章主要為大家介紹了React?Native系列之Recyclerlistview使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10react-router-domV6版本的路由和嵌套路由寫法詳解
本文主要介紹了react-router-domV6版本的路由和嵌套路由寫法詳解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考
下面小編就為大家?guī)硪黄趓eact框架使用的一些細(xì)節(jié)要點(diǎn)的思考。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05