React 18 对 Hooks 的影响 :1

简介: React 18 对 Hooks 的影响 :1
🙋🏻‍♀️ 编编拎重点:最近 React 18 发布后,部分改动对我们使用 React Hooks 有一些影响。这篇文章是蚂蚁集团前端工程师尽龙对官方文档的翻译,好让大家清晰的认识到这个改动的背景和影响。

1. 译者前言

最近 React 18 发布后,部分改动对我们使用 React Hooks 有一些影响。这篇文章对官方的文档 Update to remove the "setState on unmounted component warning"[1] 做了翻译,好让大家清晰的认识到这个改动的背景和影响。这是 React 18 对 Hooks 的影响系列第一篇,后续还会再整理其他有影响的改动,欢迎关注不迷路。

2. 翻译

2.1 背景


之前在已经卸载的组件中调用 setState时,会有一个警告,本次我们将这个警告移除了。警告内容如下:

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.

警告:不能在已经卸载的组件中更改 state。这是一个无用的操作,它表明你的项目中存在内存泄漏。要解决这个问题,请在 useEffect 清理函数中取消所有订阅和异步任务。

不幸的是,这个警告经常被误解,并且会误导大家。

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

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

在这个例子中,如果你忘记了在 effect 清理函数中调用 unsubscribe,那肯定是有内存泄漏的。

2.2 为什么说这个警告会误导大家呢?


事实上,上面的场景并不常见。反而如下场景是更常见的:

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

在上面的代码中,如果发送请求时,组件卸载了,会抛出警告。但是,在这种场景下,警告误导了大家。

这里其实没有内存泄漏:

  • Promise 会很快完成执行,然后内存被垃圾回收机制回收
  • 即使没有很快完成执行,这个警告也是没用的,因为垃圾回收也还是得等 Promise 执行完回收,你啥也不能做

一般,我们会通过如下代码来消除警告:

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)
  }
}

实际上,这种写法是没用的,并没有解决所谓的“内存泄漏”,它仅仅只是抑制了警告。正如前面说的,这里其实是没有内存泄漏的。内存会随着 Promise 执行完而释放,并没有什么在无限执行。

2.3 上述抑制警告方案比不处理更糟糕


上述抑制警告的解决方案,现在非常非常普遍。但它其实没任何好处,反而比不处理更糟糕:

  • 未来,React 会提供一个新能力,在组件卸载不可见时,我们会保存组件现在的 state,但仍会卸载组件。下次加载组件的时候,我们会用之前保存的 state 来渲染组件,以便恢复之前的页面。在组件卸载之后,setPending(false)不会被执行到,所以 pending会一直是 true,那下次恢复组件的时候,看起来是请求没有执行完成,会变的更糟糕。(译者注:关于这一块详细的行为和影响面,下一篇文章介绍)
  • 假设用户点击一个按钮,发起一个网络请求,请求结束后更新 state。为了避免这个警告,有些人会将请求行为放到 useEffect 中,因为在 useEffect 中可以监听到组件卸载,以忽略后续的 state 更新,消除警告。这样代码变的非常不清晰,非常糟糕!就是因为这个错误的警告,会让大家写出更烂的代码。

2.4 移除警告


最终,我们决定移除这个警告。这个警告想解决的订阅问题,在日常代码中并不常见。大部分情况下,它反而会误导大家,为了避免告警写出更烂的代码。希望这个警告的移除,可以让你移除代码中的 isMounted

3. 译者总结

在 ahooks 中的 useUnmountedRef[2]useSafeState[3] 等都是为了解决这个警告而生的。同时我们在 ahooks 中必要的地方,为了避免这个告警,也会在组件卸载后,忽略后续的 setState

目前来看,这些代码是多余的,后续 ahooks 会陆续优化相关场景,但不会太快。因为在 react 16、17 中这个告警仍然会有,会对新人造成不必要的困扰。我们会等 React 18 覆盖面比较广之后,再进行代码优化。

以后在代码中大家应该不需要再考虑这个告警了,不需要再使用 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


相关文章
|
27天前
|
设计模式 存储 前端开发
React开发设计模式及原则概念问题之自定义Hooks的作用是什么,自定义Hooks设计时要遵循什么原则呢
React开发设计模式及原则概念问题之自定义Hooks的作用是什么,自定义Hooks设计时要遵循什么原则呢
|
2月前
|
前端开发 JavaScript 安全
TypeScript在React Hooks中的应用:提升React开发的类型安全与可维护性
【7月更文挑战第17天】TypeScript在React Hooks中的应用极大地提升了React应用的类型安全性和可维护性。通过为状态、依赖项和自定义Hooks指定明确的类型,开发者可以编写更加健壮、易于理解和维护的代码。随着React和TypeScript的不断发展,结合两者的优势将成为构建现代Web应用的标准做法。
|
13天前
|
JavaScript 前端开发 安全
[译] 使用 TypeScript 开发 React Hooks
[译] 使用 TypeScript 开发 React Hooks
|
15天前
|
前端开发 JavaScript API
React Hooks 的使用场景有哪些?
【8月更文挑战第25天】
29 2
|
15天前
|
存储 前端开发 JavaScript
React Hooks的魔法:如何在组件世界里施展响应式与复用的魔法
【8月更文挑战第27天】React Hooks 是自 React 16.8 起新增的功能,支持开发者在无需类组件的情况下利用 React 的状态管理和特性。本文通过实例展示了多种核心 Hooks 的使用方法:`useState` 用于实现响应式状态管理;`useEffect` 处理副作用操作,如数据获取等;`useMemo` 和 `useCallback` 有助于性能优化;`useRef` 则提供对 DOM 的直接引用。
26 2
|
21天前
|
前端开发 JavaScript
react hooks深拷贝后无法保留视图状态
react hooks深拷贝后无法保留视图状态
|
11天前
|
容器 Kubernetes Docker
云原生JSF:在Kubernetes的星辰大海中,让JSF应用乘风破浪!
【8月更文挑战第31天】在本指南中,您将学会如何在Kubernetes上部署JavaServer Faces (JSF)应用,享受容器化带来的灵活性与可扩展性。文章详细介绍了从构建Docker镜像到配置Kubernetes部署全流程,涵盖Dockerfile编写、Kubernetes资源配置及应用验证。通过这些步骤,您的JSF应用将充分利用Kubernetes的优势,实现自动化管理和高效运行,开启Java Web开发的新篇章。
22 0
|
11天前
|
前端开发
【实战指南】React Hooks 详解超厉害!六个步骤带你提升 React 应用状态管理,快来探索!
【8月更文挑战第31天】React Hooks 是 React 16.8 推出的新特性,允许在函数组件中使用状态及其它功能而无需转换为类组件。通过以下六个步骤可有效提升 React 应用的状态管理:1)使用 `useState` Hook 添加状态;2)利用 `useEffect` Hook 执行副作用操作;3)在一个组件中结合多个 `useState` 管理不同状态;4)创建自定义 Hook 封装可重用逻辑;5)借助 `useContext` 访问上下文以简化数据传递;6)合理运用依赖项数组优化性能。React Hooks 为函数组件带来了更简洁的状态管理和副作用处理方式。
16 0
|
1月前
|
前端开发 开发者
彻底颠覆!React Hooks带来前端开发的革命,你准备好了吗?
【8月更文挑战第6天】在现代Web开发中,React作为顶级前端框架,以高效性能和丰富生态著称。React Hooks自16.8版本引入,赋予函数组件使用状态和生命周期的能力,使代码更简洁、模块化,易于维护。常用Hooks如`useState`、`useEffect`等简化了状态管理和副作用操作。Hooks不仅增强了组件能力,提高了代码可读性和可维护性,还在各种应用场景中展现出强大功能,尤其是在中大型项目中优化了代码结构和提升了开发效率。总之,React Hooks为前端开发注入了新活力,推动了更高效便捷的开发实践。
33 1
|
18天前
|
前端开发
使用 React Hooks 的三个主要好处
【8月更文挑战第24天】
22 0

热门文章

最新文章