React正式发布v18.0.0

一、前言
本文基于开源项目:

https://github.com/facebook/react

React18在几个小时前发布了release,我们一起来看看。


重大变化抢先看:自动批处理、严格模式、一致的 useEffect 计时、更严格的水合错误、挂起树总是一致的、带有悬念的布局效果、新的 JS 环境要求。
二、新特性
React
useId是一个新的钩子,用于在客户端和服务器上生成唯一 ID,同时避免水合不匹配。它主要用于与需要唯一 ID 的可访问性 API 集成的组件库。这解决了 React 17 及更低版本中已经存在的问题,但在 React 18 中更为重要,因为新的流式服务器渲染器如何无序交付 HTML。
startTransition并useTransition让您将一些状态更新标记为不紧急。默认情况下,其他状态更新被认为是紧急的。React 将允许紧急状态更新(例如,更新文本输入)以中断非紧急状态更新(例如,呈现搜索结果列表)。
useDeferredValue让您推迟重新渲染树的非紧急部分。它类似于去抖动,但与之相比有一些优点。没有固定的时间延迟,因此 React 将在第一次渲染反映在屏幕上后立即尝试延迟渲染。延迟渲染是可中断的,不会阻止用户输入。
useSyncExternalStore是一个新的钩子,它允许外部存储通过强制对存储的更新同步来支持并发读取。它消除了useEffect在实现对外部数据源的订阅时的需要,并且推荐用于任何与 React 外部状态集成的库。
useInsertionEffect是一个新的钩子,它允许CSS-in-JS 库解决在渲染中注入样式的性能问题。除非您已经构建了 CSS-in-JS 库,否则我们不希望您使用它。这个钩子将在 DOM 发生变异之后运行,但在布局效果读取新布局之前。这解决了在 React 17 及更低版本中已经存在的问题,但在 React 18 中更为重要,因为 React 在并发渲染期间屈服于浏览器,使其有机会重新计算布局。
React DOM Client
react-dom/client

createRootrender: 为or创建根的新方法unmount。使用它代替ReactDOM.render. 没有它,React 18 中的新功能就无法工作。
hydrateRoot: 水合服务器渲染应用程序的新方法。使用它而不是 ReactDOM.hydrate与新的 React DOM 服务器 API 结合使用。没有它,React 18 中的新功能就无法工作。
两者都createRoot接受hydrateRoot一个新选项onRecoverableError,以防你想在 React 从渲染期间的错误中恢复或日志记录时收到通知。默认情况下,React 将使用reportError, 或console.error在较旧的浏览器中。
React DOM Server
react-dom/server
完全支持流式传输 Suspense:
renderToPipeableStream: 用于 Node 环境中的流式传输。
renderToReadableStream:适用于现代边缘运行时环境,例如 Deno 和 Cloudflare worker。
现有renderToString方法继续有效,但不鼓励使用。
三、弃用了哪些呢
react-dom
react-dom:ReactDOM.render已弃用。使用它会警告并在 React 17 模式下运行您的应用程序。
react-dom:ReactDOM.hydrate已弃用。使用它会警告并在 React 17 模式下运行您的应用程序。
react-dom:ReactDOM.unmountComponentAtNode已弃用。
react-dom:ReactDOM.renderSubtreeIntoContainer已弃用。
react-dom/server:ReactDOMServer.renderToNodeStream已弃用。
四、升级
安装最新版
npm install react react-dom
# or
yarn add react react-dom


首次安装的话,在控制台中看到一个警告:

React 18 不再支持 ReactDOM.render。请改用 createRoot。在您切换到新的 API 之前,您的应用程序会像运行 React 17 一样运行。

React 18 引入了一个新的根 API,它为管理根提供了更好的人体工程学。新的根 API 还启用了新的并发渲染器,它允许您选择使用并发功能。

createRoot

import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App tab="home" />);
将unmountComponentAtNode改为root.unmount

root.unmount();
渲染中删除了回调

function AppWithCallbackAfterRender() {
  useEffect(() => {
    console.log('rendered');
  });

return <App tab="home" />
}

const container = document.getElementById('app');
const root = ReactDOM.createRoot(container);
root.render(<AppWithCallbackAfterRender />);
服务器端渲染

import { hydrateRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = hydrateRoot(container, <App tab="home" />);
// 与 createRoot 不同,您不需要在此处单独调用 root.render()
五、最后
    在我们阅读完官方文档后,我们一定会进行更深层次的学习,比如看下框架底层是如何运行的,以及源码的阅读。
    这里广东靓仔给下一些小建议:
在看源码前,我们先去官方文档复习下框架设计理念、源码分层设计
阅读下框架官方开发人员写的相关文章
借助框架的调用栈来进行源码的阅读,通过这个执行流程,我们就完整的对源码进行了一个初步的了解
接下来再对源码执行过程中涉及的所有函数逻辑梳理一遍


作者:广东靓仔


欢迎关注:前端早茶