的文章本文是React官方2022.03.08发表的一篇文章《How to Upgrade to the React 18 Release Candidate[1]》的翻译。通过这篇文章,你可以对React18的新特性有一个全面的了解。接下来,我也会翻译其他几篇React18的重要文章,让我以更好的姿态使用React18,专注不迷路。今天,我们发布了React18RC。正如我们在ReactConf[2]上分享的那样,React18基于并发模式,在提供增量升级方法的同时带来了更多的能力。在本文中,我们将带你一步步升级到React18。安装使用@rc标签安装最新版本的React。##npm$npminstallreact@rcreact-dom@rc##yarn$yarnaddreact@rcreact-dom@rcClientRenderingAPIUpdate当你第一次安装React18时,你会看到这个警告:ReactDOM.renderisnoReact18不再支持。请改用createRoot。在您切换到新的API之前,您的应用程序的行为就像在运行React17一样。了解更多信息:https://reactjs.org/link/switch-to-createroot[3]。React18提供了更合理的初始化API,使用这个API,会自动开启并发模式://Beforeimport{render}from'react-dom';constcontainer=document.getElementById('app');render(,container);//Afterimport{createRoot}from'react-dom/client';constcontainer=document.getElementById('app');constroot=createRoot(container);root.render();同时,我们将卸载方法从unmountComponentAtNode改为root.unmount://BeforemountComponentAtNode(container);//Afterroot.unmount();我们去掉了ReactDOM.render函数的回调,因为在使用Susponse的时候,它有问题://Beforeconstcontainer=document.getElementById('app');ReactDOM.render(,container,()=>{console.log('rendered');});//AfterfunctionAppWithCallbackAfterRender(){useEffect(()=>{console.log('rendered');});返回}constcontainer=document.getElementById('app');constroot=ReactDOM.createRoot(容器);root.render();最后,如果使用hydration实现SSR,则需要将hydrate替换为hydrateRoot://Beforeimport{hydrate}from'react-dom';constcontainer=document.getElementById('app');hydrate(,container);//Afterimport{hydrateRoot}from'react-dom/client';constcontainer=document.getElementById('app');constroot=hydrateRoot(container,);//与createRoot不同,这里不需要单独的root.render()调用。有关详细信息,请参阅ReplacingrenderwithcreateRoot[4]SSRAPIupdateinReact18,以支持服务器端的Suspense和流式SSR优化react-dom/server的API。使用以下API,将抛出警告:renderToNodeStream:Deprecated???。相反,对于Node环境中的流式传输,请使用:renderToPipeableStream:已添加?。我们还引入了一个新的API来支持现代边缘运行时(例如Deno和Cloudflareworker)上的流式SSR和Suspense:renderToReadableStream:已添加?。以下两个API可以继续使用,但不支持Suspense:renderToString:限制??。renderToStaticMarkup:限制??。以下API没有改变:renderToStaticNodeStream。有关更多信息,请参阅在服务器上升级到React18[5]、React18中的新SuspenseSSR架构[6]。AutomaticbatchprocessingAutomaticBatching批处理是指:React将多个状态更新聚合到一个render中执行,以提高性能。在React18之前,批处理只能在React自带的事件机制中使用,但是在Promise、setTimeout、原生事件等场景中,是无法使用批处理的。React18支持更多场景下的批处理,提供更好的性能。//在React18之前,只有React事件会使用批处理函数handleClick(){setCount(c=>c+1);设置标志(f=>!f);//React只会重新渲染一次,这是批处理}setTimeout(()=>{setCount(c=>c+1);setFlag(f=>!f);//React会渲染两次,一次for每个状态变化},1000);使用createRoot初始化React18后,无论应用场景如何,所有状态更新都会自动使用批处理。//React18之后,Promise、setTimeout、native事件会自动批处理functionhandleClick(){setCount(c=>c+1);设置标志(f=>!f);//React只会重新渲染一次,这是批处理}setTimeout(()=>{setCount(c=>c+1);setFlag(f=>!f);//React只会重新渲染一次,这是批处理},1000);这是一项重大更改,但我们希望这能提高您的产品性能。当然,你仍然可以使用flushSync手动取消批处理并强制同步执行:import{flushSync}from'react-dom';functionhandleClick(){flushSync(()=>{setCounter(c=>c+1);});//React更新DOM一次flushSync(()=>{setFlag(f=>!f);});//React更新DOM一次}有关更多信息,请参阅React18[7]中更少渲染的自动批处理。三方库API在React18中,我们与三方库作者合作,定义了一些新的API来满足三方库在并发模式下特定场景的需求。比如样式管理、外部状态管理、可访问性(accessibility)等场景。为了支持React18,一些第三方库可能需要使用如下API:useId是一个新的Hook,支持在客户端和服务端生成唯一的ID,同时避免水合不兼容。React17可以解决,低版本一直有问题。在React18中,这个问题尤为重要,因为流式SSR返回的HTML片段是乱序的。有关详细信息,请参阅发货意向:useId[8]。useSyncExternalStore是一个新的Hook,它允许外部状态管理器强制立即同步更新以支持并发读取。推荐所有.React外部状态管理库。有关详细信息,请参阅useSyncExternalStore概述帖子[9]、useSyncExternalStoreAPI详细信息[10]。useInsertionEffect是一个新的Hook,它解决了CSS-in-JS库在渲染中动态注入样式的性能问题。除非您构建了CSS-in-JS库,否则我们不希望您使用它。这个Hook在DOM生成之后,LayoutEffect执行之前执行。有关详细信息,请参阅样式[11]的库升级指南。React18还引入了用于并发渲染的新API,例如startTransition和useDeferredValue,更多内容将在即将发布的稳定版本中共享。StrictModeStrictMode未来我们希望增加一个特性,让React保存组件的状态,但是移除UI部分。例如,当返回到旧页面时,React会立即恢复之前的内容。为此,React将使用之前保存的状态重新加载组件。这个特性会给React项目带来非常好的体验,但是需要组件支持在状态不变的情况下多次卸载和重新加载组件。为了检查组件写法不当,React18在开发模式下渲染组件时,会自动执行一次卸载和重新加载行为,以检查组件是否支持状态不变,组件卸载和重新加载的场景。以前React加载组件的逻辑是:*React挂载组件。*布局效果已创建。*效果效果被创建。在React18严格模式的开发环境中,React会模拟卸载和重新加载组件:*React挂载组件。*布局效果已创建。*Effect效果被创建。*React模拟卸载组件。*布局效果被破坏。*效果被破坏。*React模拟使用先前状态安装组件。*布局效果设置代码运行*有关效果设置代码运行的更多信息,请参阅:将严格效果添加到严格模式[12]、如何支持严格效果[13]。配置测试环境第一次在测试用例中使用createRoot时,您会看到以下警告:当前测试环境未配置为支持act(...)。要解决此问题,您需要在执行用例之前将globalThis.IS_REACT_ACT_ENVIRONMENT设置为true。//在你的测试设置文件中globalThis.IS_REACT_ACT_ENVIRONMENT=true;这个标志告诉React它正在一个类似单元测试的环境中运行。如果你忘记使用act,React会打印一些有用的警告。您还可以将标志设置为false以告诉React不需要act。这对于模拟浏览器环境的端到端测试很有用。当然,我们希望测试库自动为你添加这个配置。例如,下一个版本的ReactTestingLibrary已经内置了对React18的支持,无需任何额外的配置。可以在以下位置找到更多信息:有关行为测试API和相关更改的更多背景信息[14]。删除IE支持在这个版本中,React将放弃对InternetExplorer的支持。我们做这个改动是因为React18引入的新特性是基于现代浏览器开发的,有些能力在IE上是不支持的,比如微任务。如果您需要支持InternetExplorer,我们建议继续使用React17。其他更改删除了“setStateonunmountedcomponent”警告[15]。Susponse不再强制执行回退属性[16]。组件支持渲染undefined[17]。弃用renderSubtreeIntoContainer[18]。严格模式不再忽略自动重新渲染组件的log[19]。参考[1]如何升级到React18ReleaseCandidate:https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html。[2]ReactConf:https://reactjs.org/blog/2021/12/17/react-conf-2021-recap.html。[3]https://reactjs.org/link/switch-to-createroot:https://reactjs.org/link/switch-to-createroot。[4]用createRoot替换render:https://github.com/reactwg/react-18/discussions/5。[5]升级到React18在服务器上:https://github.com/reactwg/react-18/discussions/22。[6]React18中新的SuspenseSSR架构:https://github.com/reactwg/react-18/discussions/37[7]React18中更少渲染的自动批处理:https://github.com/reactwg/react-18/discussions/21。[8]发货意向:useId:https://github.com/reactwg/react-18/discussions/111。[9]useSyncExternalStore概述帖子:https://github.com/reactwg/react-18/discussions/70。[10]useSyncExternalStoreAPI详细信息:https://github.com/reactwg/react-18/discussions/86。[11]样式库升级指南:https://github.com/reactwg/react-18/discussions/110。[12]为严格模式添加严格效果:https://github.com/reactwg/react-18/discussions/19。[13]如何支持严格效果:https://github.com/reactwg/react-18/discussions/18。[14]有关行为测试API和相关更改的更多背景信息:https://github.com/reactwg/react-18/discussions/102。[15]删除“setStateonunmountedcomponent”警告:https://github.com/reactwg/react-18/discussions/82。[16]Susponse不再强制执行fallback属性:https://github.com/reactwg/react-18/discussions/72。[17]组件支持呈现未定义:https://github.com/reactwg/react-18/discussions/75。[18]弃用renderSubtreeIntoContainer:https://github.com/facebook/react/pull/23355。[19]严格模式不再忽略自动二次渲染组件的日志:https://github.com/reactwg/react-18/discussions/96。