成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

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

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

結果發現因為 React 的行為不一致導致了一些看得見的和看不見的 bug,真的是一場災難。

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

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

問題

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

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

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

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

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

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

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

useEffect 的清理時機

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

在 React 17 中,副作用的執行時機發生了變化,一個破壞性的效果是:如果組件卸載,副作用的清理時機是異步的,對應的回調函數執行也同樣是異步的。是的,異步

卸載時的要執行的回調函數,對于狀態和方法的訪問,問題不大,它們是不可變的,能通過閉包的方式訪問到的。

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

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

這里有一個簡單的在線 demo,感興趣可以看看,當 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 可以保證回調函數 同步 執行,這樣就能確保 ref 此時還是最后的值,而不是被設置為 null。

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

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

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

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

結尾

版本升級這件事情,還是得權衡利弊。

責任編輯:姜華 來源: 今日頭條
相關推薦

2010-06-21 10:34:03

職場信號被炒

2022-03-25 08:31:09

ReactReact 18升級

2018-06-20 15:50:38

JDK9JVMJDK10

2020-06-19 09:00:21

人工智能AI計算機視覺

2019-12-30 11:07:02

Https免費腳本

2013-10-21 10:07:30

微軟Windows 8.1理由

2018-07-16 14:23:30

代碼Android問題

2013-08-20 09:59:25

Windows 8.1微軟操作系統

2024-08-09 14:13:51

2013-12-04 11:31:42

Linux MintLinux Mint Linux Mint

2021-09-09 11:24:09

微軟Windows 11Windows

2010-09-03 14:54:42

VMwareSaaS

2011-09-27 09:13:16

Ubuntu 11.0

2011-02-18 09:06:15

ChromeChrome DevLinux

2020-01-13 10:00:32

升級Windows 10Windows

2021-06-21 15:49:39

React動效組件

2012-02-24 09:46:24

VMware存儲vSphere 5

2022-09-12 21:10:42

LinkerdKubernetes

2023-07-21 01:12:30

Reactfalse?變量

2014-04-30 15:44:11

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费一级黄色录像 | 日韩午夜一区二区三区 | 亚洲永久精品国产 | 亚洲精品久久视频 | 日本亚洲欧美 | 青青操91| 国产一二三区电影 | 色精品视频 | 日韩中文在线 | 在线免费观看欧美 | 国产 日韩 欧美 在线 | 成人精品国产免费网站 | 日韩欧美一区二区在线播放 | 国产精品99久久久久久www | 福利精品在线观看 | 日韩精品成人一区二区三区视频 | 成人在线a| 99久久99| 看一级毛片视频 | 日本一区二区高清不卡 | 中文字幕精品一区二区三区精品 | 亚洲精品视频网站在线观看 | 91一区二区三区在线观看 | 九色在线观看 | 欧美成人第一页 | 国产伦精品一区二区三毛 | 日韩在线国产精品 | 久久久性色精品国产免费观看 | 99re视频| 97av视频在线 | 亚洲一区二区精品视频 | 日韩欧美在线不卡 | 精品国产一区二区久久 | 欧美日韩国产精品一区二区 | 亚洲免费视频网址 | 999在线精品| 伊人网在线播放 | 91欧美精品成人综合在线观看 | 国产精品一区二区在线 | 一级毛片视频 | 久久久精品一区二区三区 |