如何启用React并发模式

译文摘自:Kent C. Dodds 博客
前言
如何启用React并发模式

文章插图
Photo by Marc Schulte
并发模式对用户体验和开发人员体验而言是一个巨大的改进 。启用方法如下 。
React的新并发模式刚刚在 实验发行版中发布 。这是多年研究的结果,并证明了这一点 。如果您想了解更多有关为何如此酷的知识,请一定要观看 Dan Abramov在JSIceland的演讲 。人们开始使用它,看到一些不错的性能优势 。
所有这些,请记住,这是实验性的 。实验性发布渠道不尊重semver(因此,依赖它的代码可能会意外中断),并且肯定存在错误 。但是早期的实验对许多人来说都是有希望的,我建议您在自己的应用中尝试一下 。
一、安装它
首先,要启用并发模式,您需要具有支持此功能的React版本 。在撰写本文时,React和React DOM的版本 16.11.0不支持并发模式 。因此,我们需要安装该 experimental版本:
npm install react@experimental react-dom@experimental# or: yarn add react@experimental react-dom@experimental二、确保运行
确保您的应用正常运行,而无需进行其他任何更改 。
运行您的应用程序,运行构建,运行测试/类型检查 。如果 控制台中没有以前没有的新错误,则可能是React中的错误,您应该尝试进行最小程度的复制(最好在codeandbox中),然后 在React repo上打开一个新问题 。
通常,我们会跳过这一步,但是我认为重要的是要确保如果有问题,您知道这些问题是从哪一步开始的!好的建议,我一般会说
三、启用并发模式
在项目的入口文件中,您可能会有类似以下内容的内容:
【如何启用React并发模式】import React from 'react'import ReactDOM from 'react-dom'import App from './app'const rootEl = document.getElementById('root')ReactDOM.render(, rootEl)要启用并发模式,您将使用新的 createRoot API:
import React from 'react'import ReactDOM from 'react-dom'import App from './app'const rootEl = document.getElementById('root')// ReactDOM.render(, rootEl)const root = ReactDOM.createRoot(rootEl)root.render()而已 。
四、无需更改
确保您的应用正常运行,而无需进行其他任何更改 。
运行您的应用程序,运行构建,运行测试/类型检查 。如果 控制台中没有以前没有的新错误,则可能是React中的错误,您应该尝试进行最小程度的复制(最好在codeandbox中),然后 在React repo上打开一个新问题 。
如果看起来很熟悉,那是因为我从步骤2中复制/粘贴了它
但是,在这种情况下,如果发生故障或控制台中出现新错误 。可能是因为您的应用中有一些代码正在使用并发模式下不支持的功能(例如字符串引用,旧版上下文或 findDOMNode) 。
另外请注意,所有带有unsafe_前缀的生命周期方法现在实际上都是不安全的,使用它们会导致错误 。
五、试用并发模式 。
并发模式为我们启用了两个主要功能:
  1. 时间分片
  2. 悬念一切异步
如果您的应用程序中有一些用户交互很慢,请尝试一下,如果它不那么麻烦,那就是在工作中进行切片(有关更多信息,请参见Dan的演讲链接) 。
您可以尝试将您的一种异步交互重构为悬念,或者尝试将其添加到应用程序中的某个位置:
const TRANSITION_CONFIG = { timeoutMs: 3000, //Play with this number a bit...}function SuspenseDemo() { const [greetingResource, setGreetingResource] = React.useState(null) const [startTransition, isPending] = React.useTransition(TRANSITION_CONFIG) function handleSubmit(event) { event.preventDefault() const name = event.target.elements.nameInput.value startTransition(() => { setGreetingResource(createGreetingResource(name)) }) } return ( Suspense Demo loading greeting}>
)}function Greeting({greetingResource, isPending}) { return ({greetingResource ? greetingResource.read() : 'Please submit a name'}
)}// make this function do something else. Like an HTTP request or somethingfunction getGreeting(name) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(`Hello ${name}!`) // try rejecting instead... (make sure to comment out the resolve call) // reject(new Error(`Oh no. Could not load greeting for ${name}`)) }, 1500) // play with this number a bit })}// This should NOT be copy/pasted for production code and is only here// for experimentation purposes. The API for suspense (currently throwing a// promise) is likely to change before suspense is officially released.function createGreetingResource(name) { let status = 'pending' let result let suspender = getGreeting(name).then( greeting => { status = 'success' result = greeting }, error => { status = 'error' result = error }, ) return { read() { if (status === 'pending') throw suspender if (status === 'error') throw result if (status === 'success') return result }, }}class ErrorBoundary extends React.Component { state = {error: null} static getDerivedStateFromError(error) { return {error} } componentDidCatch() { // log the error to the server } tryAgain = () => this.setState({error: null}) render() { return this.state.error ? (


推荐阅读