React 18 正式发布了

早上上班打开 React 官网 发现React 18 正式发布了,看了下更新记录,干货满满呀。

官方更新记录地址

一. 放弃对 Internet Explorer 的支持

React 18 将放弃对 Internet Explorer 的支持,IE 将于 2022 年 6 月 15 日停止维护。 React 18 中引入的新功能是使用现代浏览器功能构建的,例如无法在 IE 中充分填充的微任务。

如果需要支持 Internet Explorer,建议继续使用 React 17

二. 新功能

1. 并发渲染

这个之前已经爆料好多次了,并发本身不是一个特性。这是一种新的幕后机制,使 React 能够同时准备多个版本的 UI。可以将并发视为一个实现细节——它之所以有价值,是因为它解锁了一些特性。React 在其内部实现中使用了复杂的技术,例如优先级队列和多重缓冲。但是不会在公共 API 中的任何地方看到这些概念。

2. 自动批处理

批处理是 React 将多个状态更新分组到一个重新渲染中以获得更好的性能。如果没有自动批处理,只能在 React 事件处理程序中批处理更新。默认情况下,PromisesetTimeout、本机事件处理程序或任何其他事件内部的更新不会在 React 中批处理。使用自动批处理,这些更新将自动批处理。

1
// 在 React 18 之前,只有 React 事件被批处理
2
3
function handleClick() {
4
  setCount(c => c + 1)
5
  setFlag(f => !f)
6
  // React 只会在最后重新渲染一次(这就是批处理!)
7
}
8
9
setTimeout(() => {
10
  setCount(c => c + 1)
11
  setFlag(f => !f)
12
  // React 将渲染两次,每次状态更新一次(无批处理)
13
}, 1000)

这是一项重大更改,这会减少工作渲染,从而提高应用程序的性能。要退出自动批处理,可以使用 flushSync

1
import { flushSync } from 'react-dom'
2
3
function handleClick() {
4
  flushSync(() => {
5
    setCounter(c => c + 1)
6
  })
7
8
  // React 现在已经更新了 DOM
9
  flushSync(() => {
10
    setFlag(f => !f)
11
  })
12
  // React 现在已经更新了 DOM
13
}

3. 过渡

过渡是 React 18 中引入的一个新的并发特性,用于区分紧急和非紧急更新。它允许您将更新标记为过渡。对应新增的 api

React.startTransitionReact.useTransition

4. 新的 Suspense 功能

如果组件树的一部分尚未准备好显示,Suspense 允许您以声明方式指定组件树的加载状态:

1
<Suspense fallback={<Spinner />}>
2
  <Comments />
3
</Suspense>

Suspense 使 UI 加载状态 成为 React 编程模型中一流的声明性概念。这可以在它之上构建更高级别的功能。在 React 18中,在服务器上添加了对Suspense 的支持,并使用并发渲染特性扩展了它的功能。

5. render api 变更

createRoot render 替换 原来的 ReactDOM.rendercreateRoot 现在从 react-dom/client 上导出。

原来的

1
import { render } from 'react-dom'
2
const container = document.getElementById('app')
3
render(<App tab='home' />, container)

现在的

1
import { createRoot } from 'react-dom/client'
2
const container = document.getElementById('app')
3
const root = createRoot(container)
4
root.render(<App tab='home' />)

可以使用unmount以下命令卸载 root。

1
root.unmount()

6. 服务端 api 变更

这些新的 API 现在从 react-dom/server 上导出并完全支持流式传输 Suspense

renderToPipeableStream: 用于 Node 环境中的流式传输。

renderToReadableStream:适用于现代边缘运行时环境,例如 DenoCloudflare worker

现有 renderToString 方法继续有效,但不鼓励使用。

renderToNodeStream已弃用


以下 API 将继续工作,但对 Suspense 的支持有限:

renderToStringrenderToStaticMarkup


renderToStaticNodeStream : 此 API 将继续用于呈现电子邮件

7. 新的严格模式行为

8. 新增 hooks

useId

useId 是一个新的钩子,用于在客户端和服务器上生成唯一 ID,同时避免水合不匹配。它主要用于与需要唯一 ID 的可访问性 API 集成的组件库。这解决了 React 17 及更低版本中已经存在的问题,但在 React 18 中更为重要,因为新的流式服务器渲染器如何无序交付 HTML。


useTransition

useTransitionstartTransition 让您将一些状态更新标记为不紧急。默认情况下,其他状态更新被认为是紧急的。React 将允许紧急状态更新(例如,更新文本输入)以中断非紧急状态更新(例如,呈现搜索结果列表) 。


useDeferredValue

useDeferredValue 让您推迟重新渲染树的非紧急部分。它类似于去抖动,但与之相比有一些优点。没有固定的时间延迟,因此 React 将在第一次渲染反映在屏幕上后立即尝试延迟渲染。延迟渲染是可中断的,不会阻止用户输入。


useSyncExternalStore

useSyncExternalStore 是一个新的钩子,它允许外部存储通过强制对存储的更新同步来支持并发读取。在实现对外部数据源的订阅时,它消除了对 useEffect 的需要,并且推荐用于任何与 React 外部状态集成的库。


useInsertionEffect
useInsertionEffect 是一个新的钩子,它允许 CSS-in-JS 库解决在渲染中注入样式的性能问题。除非您已经构建了CSS-in-JS 库,否则我们不希望您使用它。这个钩子将在 DOM 发生变异之后运行,但在布局效果读取新布局之前。这解决了在 React 17 及更低版本中已经存在的问题,但在 React 18 中更为重要,因为 React 在并发渲染期间屈服于浏览器,使其有机会重新计算布局

三. 已弃用 api

1. react-dom:ReactDOM.render 已弃用

React 17 下运行的应用程序会警告。

2. react-dom:ReactDOM.hydrate 已弃用。

React 17 下运行的应用程序会警告。

3. react-dom:ReactDOM.unmountComponentAtNode 已弃用。

4. react-dom:ReactDOM.renderSubtreeIntoContainer 已弃用。

5. react-dom/server:ReactDOMServer.renderToNodeStream 已弃用。

四.其他变化

1. 组件现在可以渲染 undefined

undefined 如果您从组件返回,React 不再发出警告。这使得允许的组件返回值与组件树中间允许的值一致。建议使用 linter 来防止忘记 return JSX 之前的语句等错误。

2. 在测试中,act 警告现在是可选的

在测试中,act 警告现在是可选的:如果您正在运行端到端测试,则 act 警告是不必要的。我们引入了一种选择加入机制,因此您只能在有用且有益的单元测试中启用它们。

3. 组件为卸载时不在警告 setState

以前,当您调用未安装的组件时,React 会警告内存泄漏。此警告是为订阅添加的,但人们主要在设置状态很好的情况下遇到它,并且变通方法会使代码变得更糟。已删除此警告。

4. 不抑制控制台日志

当您使用严格模式时,React 会渲染每个组件两次,以帮助您发现意外的副作用。在 React 17 中,抑制了两个渲染之一的控制台日志,以使日志更易于阅读。为了回应社区对此令人困惑的反馈,已经删除了抑制。相反,如果你安装了 React DevTools,第二个日志的渲染将显示为灰色,并且会有一个选项(默认关闭)来完全抑制它们。

5. 改进的内存使用

React 现在会在卸载时清理更多内部字段,从而降低应用程序代码中可能存在的未修复内存泄漏的影响。

6.服务端渲染

renderToString

在服务器上挂起时将不再出错。相反,它将为最近的<Suspense>边界发出回退HTML,然后重试在客户端上呈现相同的内容。仍然建议您切换到流式 API,例如 renderToPipeableStreamor renderToReadableStream


renderToStaticMarkup

在服务器上挂起时将不再出错。相反,它将为最近的边界发出回退 HTML,并在客户端重试渲染。


更多变更请查看官方链接 官方链接

参考链接

  1. https://reactjs.org/blog/2022/03/29/react-v18.html
  2. https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html