av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

React16升級到17的一個坑:組件銷毀時Ref可能會被重置為Null

大家好,我是前端西瓜哥。

公司主營業(yè)務(wù):網(wǎng)站制作、網(wǎng)站設(shè)計、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出蒼溪免費做網(wǎng)站回饋大家。

最近公司的項目用的 React 從 16 升到了 17 版本,選擇升級的原因是想以后將項目遷移到 Nextjs 上。

結(jié)果發(fā)現(xiàn)因為 React 的行為不一致導(dǎo)致了一些看得見的和看不見的 bug,真的是一場災(zāi)難。

React 17 是一個比較特別的版本,它沒有任何新特性,但它改造了 React 的底層,讓 React 17 可以漸進式地升級部分的模塊,為 18 版本做準(zhǔn)備。

這些改造,有一部分是破壞性的。

問題

我這里有個彈窗,彈窗里面是一些表單項。當(dāng)用戶在表單項做了一些修改,然后點擊彈窗的遮罩層時,里面的組件會銷毀掉。

在銷毀時,我們會調(diào)用一個 ref 上的 save() 方法來保存這些數(shù)據(jù)。

useEffect(() => {
return () => {
formRef.current && formRef.current.save();
}
}, []);

在 React 16 的時候是正常的,但到 React 17,失敗了,我們無法保存表單里面的數(shù)據(jù)。

一頓排查之后,我找到了問題所在:在 React 17 版本,組件銷毀時獲取的 ref.current 可能會被重置為 null。

接著我找到了官方文檔對于這種情況的說明:

https://zh-hans.reactjs.org/blog/2020/08/10/react-v17-rc.html#effect-cleanup-timing

useEffect 的清理時機

useEffect(() => {
return () => {
// 這里的執(zhí)行清理操作
}
})

在 React 17 中,副作用的執(zhí)行時機發(fā)生了變化,一個破壞性的效果是:如果組件卸載,副作用的清理時機是異步的,對應(yīng)的回調(diào)函數(shù)執(zhí)行也同樣是異步的。是的,異步。

卸載時的要執(zhí)行的回調(diào)函數(shù),對于狀態(tài)和方法的訪問,問題不大,它們是不可變的,能通過閉包的方式訪問到的。

但問題是 ref,它是可變的,我們可以隨意的設(shè)置 ref.current 的值,且不會觸發(fā)組件的重新渲染。

這個 ref 會被 React 在組件卸載時重置為 null。因為是異步的,所以我們有很大可能會喜提一個 null 值。

這里有一個簡單的在線 demo,感興趣可以看看,當(dāng) Component 組件銷毀時,elRef 變成了 null:

https://codesandbox.io/s/react-17-zhong-zu-jian-xiao-hui-shi-ref-ke-neng-bei-she-zhi-wei-null-2kl4xu。

然后是 React 16 版本的 ref,因為是同步的,所以銷毀時 ref 沒有重置為 null:

https://codesandbox.io/s/16-de-ref-shi-zheng-chang-de-18mqmd。

解決方案

官方的文檔提供了兩個解決方案。

一個是用 useLayoutEffect。

useLayoutEffect(() => {
return () => {
formRef.current && formRef.current.save();
}
}, []);

useLayoutEffect 可以保證回調(diào)函數(shù) 同步 執(zhí)行,這樣就能確保 ref 此時還是最后的值,而不是被設(shè)置為 null。

第二種方式是用一個臨時變量在 ref 每次變化時,將 ref.current 保存起來,放到副作用清理回調(diào)函數(shù)的閉包中,來保證不可變性。

useEffect(() => {
const instance = someRef.current;
instance.someSetupMethod();
return () => {
instance.someCleanupMethod();
};
});

但這里貌似還是有一點局限性:不能提供第二個參數(shù),也就是依賴項參數(shù),因為我們不能保證中途 ref 沒有發(fā)生改變。

目前我是用第一種方案來處理我遇到的問題。

結(jié)尾

版本升級這件事情,還是得權(quán)衡利弊。


文章名稱:React16升級到17的一個坑:組件銷毀時Ref可能會被重置為Null
標(biāo)題來源:http://uogjgqi.cn/article/dpgpogo.html
掃二維碼與項目經(jīng)理溝通

我們在微信上24小時期待你的聲音

解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流