自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊 React 18 對 Hooks 的影響

開發(fā) 前端
在 ahooks 中的 useUnmountedRef、useSafeState等都是為了解決這個警告而生的。同時我們在 ahooks 中必要的地方,為了避免這個告警,也會在組件卸載后,忽略后續(xù)的 setState。

一、 譯者前言

最近 React 18 發(fā)布后,部分改動對我們使用 React Hooks 有一些影響。這篇文章對官方的文檔 Update to remove the "setState on unmounted component warning"[1] 做了翻譯,好讓大家清晰的認識到這個改動的背景和影響。這是 React 18 對 Hooks 的影響系列第一篇,后面我還會整理其它有影響的改動。

二、 翻譯

1、 背景

之前在已經(jīng)卸載的組件中調(diào)用 setState時,會有一個警告,本次我們將這個警告移除了。警告內(nèi)容如下:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function。

警告:不能在已經(jīng)卸載的組件中更改 state。這是一個無用的操作,它表明你的項目中存在內(nèi)存泄漏。要解決這個問題,請在 useEffect 清理函數(shù)中取消所有訂閱和異步任務(wù)。

不幸的是,這個警告經(jīng)常被誤解,并且會誤導大家。

它原本是想保證如下示例能正常工作的:

useEffect(() => {
function handleChange() {
setState(store.getState())
}
store.subscribe(handleChange)
return () => store.unsubscribe(handleChange)
}, [])

在這個例子中,如果你忘記了在 effect 清理函數(shù)中調(diào)用 unsubscribe,那肯定是有內(nèi)存泄漏的。

2、 為什么說這個警告會誤導大家呢?

事實上,上面的場景并不常見。反而如下場景是更常見的:

async function handleSubmit() {
setPending(true)
await post('/someapi') // component might unmount while we're waiting
setPending(false)
}

在上面的代碼中,如果發(fā)送請求時,組件卸載了,會拋出警告。但是,在這種場景下,警告誤導了大家。

這里其實沒有內(nèi)存泄漏:

  • Promise 會很快完成執(zhí)行,然后內(nèi)存被垃圾回收機制回收。
  • 即使沒有很快完成執(zhí)行,這個警告也是沒用的,因為垃圾回收也還是得等 Promise 執(zhí)行完回收,你啥也不能做。

一般,我們會通過如下代碼來消除警告:

let isMountedRef = useRef(false)
useEffect(() => {
isMountedRef.current = true
return () => {
isMountedRef.current = false
}
}, [])
async function handleSubmit() {
setPending(true)
await post('/someapi')
if (!isMountedRef.current) {
setPending(false)
}
}

實際上,這種寫法是沒用的,并沒有解決所謂的“內(nèi)存泄漏”,它僅僅只是抑制了警告。正如前面說的,這里其實是沒有內(nèi)存泄漏的。內(nèi)存會隨著 Promise 執(zhí)行完而釋放,并沒有什么在無限執(zhí)行。

3、 上述抑制警告方案比不處理更糟糕

上述抑制警告的解決方案,現(xiàn)在非常非常普遍。但它其實沒任何好處,反而比不處理更糟糕:

  • 未來,React 會提供一個新能力,在組件卸載不可見時,我們會保存組件現(xiàn)在的 state,但仍會卸載組件。下次加載組件的時候,我們會用之前保存的 state 來渲染組件,以便恢復之前的頁面。在組件卸載之后,setPending(false)不會被執(zhí)行到,所以 pending會一直是 true,那下次恢復組件的時候,看起來是請求沒有執(zhí)行完成,會變的更糟糕。(譯者注:關(guān)于這一塊詳細的行為和影響面,下一篇文章介紹)。
  • 假設(shè)用戶點擊一個按鈕,發(fā)起一個網(wǎng)絡(luò)請求,請求結(jié)束后更新 state。為了避免這個警告,有些人會將請求行為放到 useEffect 中,因為在 useEffect 中可以監(jiān)聽到組件卸載,以忽略后續(xù)的 state 更新,消除警告。這樣代碼變的非常不清晰,非常糟糕!就是因為這個錯誤的警告,會讓大家寫出更爛的代碼。

4、 移除警告

最終,我們決定移除這個警告。這個警告想解決的訂閱問題,在日常代碼中并不常見。大部分情況下,它反而會誤導大家,為了避免告警寫出更爛的代碼。希望這個警告的移除,可以讓你移除代碼中的 isMounted。

三、 譯者總結(jié)

在 ahooks 中的 useUnmountedRef[2]、useSafeState[3] 等都是為了解決這個警告而生的。同時我們在 ahooks 中必要的地方,為了避免這個告警,也會在組件卸載后,忽略后續(xù)的 setState。

目前來看,這些代碼是多余的,后續(xù) ahooks 會陸續(xù)優(yōu)化相關(guān)場景,但不會太快。因為在 react 16、17 中這個告警仍然會有,會對新人造成不必要的困擾。我們會等 React 18 覆蓋面比較廣之后,再進行代碼優(yōu)化。

以后在代碼中大家應(yīng)該不需要再考慮這個告警了,不需要再使用 useUnmountedRef[4]、useSafeState[5] 等 Hooks 了。

參考資料

[1]Update to remove the setState on unmounted component warning: https://github.com/reactwg/react-18/discussions/82。

[2]useUnmountedRef: https://ahooks.js.org/hooks/use-unmounted-ref。

[3]useSafeState: https://ahooks.js.org/hooks/use-safe-state。

[4]useUnmountedRef: https://ahooks.js.org/hooks/use-unmounted-ref。

[5]useSafeState: https://ahooks.js.org/hooks/use-safe-state。

責任編輯:姜華 來源: 前端技術(shù)磚家
相關(guān)推薦

2021-05-11 08:48:23

React Hooks前端

2019-08-20 15:16:26

Reacthooks前端

2023-11-06 08:00:00

ReactJavaScript開發(fā)

2020-10-28 09:12:48

React架構(gòu)Hooks

2024-09-23 14:52:49

2021-03-18 08:00:55

組件Hooks React

2020-09-19 17:46:20

React Hooks開發(fā)函數(shù)

2022-08-21 09:41:42

ReactVue3前端

2019-03-13 10:10:26

React組件前端

2022-04-16 20:10:00

React Hookfiber框架

2023-05-08 07:52:29

JSXReactHooks

2022-02-10 19:15:18

React監(jiān)聽系統(tǒng)模式

2022-07-18 09:01:58

React函數(shù)組件Hooks

2022-03-16 22:24:50

ReactstateHooks

2020-08-10 06:31:01

React Hooks前端開發(fā)

2021-11-05 10:36:19

性能優(yōu)化實踐

2022-04-14 11:50:39

函數(shù)組件hook

2020-03-16 10:25:49

前端React Hooks響應(yīng)式布局

2022-06-23 09:04:14

ReactHooks項目

2021-05-21 06:13:35

React Hooks react-refrReact
點贊
收藏

51CTO技術(shù)棧公眾號