目录
React18 新增特性
作者:kerwin
版本:QF1.0
版权:千锋HTML5大前端教研院
公众号: 大前端私房菜
一. React18介绍
1. 新的项目创建
npx create-react-app my-app
cd my-app
npm start
2. 老的项目升级
//先把依赖中的版本号改成最新,然后删掉 node_modules 文件夹,
//"react": "^18.2.0",
//"react-dom": "^18.2.0"
npm i
如果您在使用 Node.js 17 的应用程序中遇到ERR_OSSL_EVP_UNSUPPORTED错误,很可能是您的应用程序或您正在使用的模块尝试使用 OpenSSL 3.0 默认不再允许的算法或密钥大小。
$env:NODE_OPTIONS="--openssl-legacy-provider"
二. Render API
React 18 引入了一个新的 root API,支持 new concurrent renderer(并发模式的渲染)
老的写法
import ReactDOM from 'react-dom';
ReactDOM.render(<App/>,document.getElementById("root"))
新的写法
import ReactDOM from 'react-dom/client';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
三.自动批量更新State
React 18 默认开启批处理来实现性能提升。
支持批处理:
- React 事件处理函数
- promise
- setTimeout
- 原生事件处理
不要开启严格模式测试
1. setTimeout
/*
* @作者: kerwin
*/
import React, { useState } from 'react'
export default function App() {
console.log("render")
const [name,setName] = useState("kerwin")
const [age,setAge] = useState(100)
return (
<div>
{name}-{age}
<button onClick={() => {
setTimeout(() => {
setName("xiaoming")
setAge(18)
},0)
}}>click</button>
</div>
)
}
2. promise
/*
* @作者: kerwin
*/
import React, { useState } from 'react'
const ajax = ()=>{
return new Promise((resolve)=>{
resolve()
})
}
export default function App() {
console.log("render")
const [name,setName] = useState("kerwin")
const [age,setAge] = useState(100)
return (
<div>
{name}-{age}
<button onClick={() => {
ajax().then(res=>{
setName("xiaoming")
setAge(18)
})
}}>click</button>
</div>
)
}
3.原生事件
/*
* @作者: kerwin
*/
import React, { useState,useEffect } from 'react'
export default function App() {
console.log("render")
const [name,setName] = useState("kerwin")
const [age,setAge] = useState(100)
useEffect(() => {
document.body.addEventListener("click",()=>{
console.log("click")
setName("xiaoming")
setAge(18)
},false)
}, [])
return (
<div>
{name}-{age}
</div>
)
}
4. flushSync
flushSync(()=>{
setName("xiaoming")
})
flushSync(()=>{
setAge(18)
})
四. Concurrent Mode(并发模式)
CM 本身并不是一个功能,而是一个底层设计,它使 React 能够同时准备多个版本的 UI。
-
在之前的React 状态变更后,会开始准备虚拟 DOM,然后渲染真实 DOM,整个流程是串联的。一旦开始触发更新,只能等流程结束,期间是无法被中断的。
-
在 并发模式下,React 在执行过程中,每执行一个 Fiber,都会检查有没有更高优先级的更新,如果有,则的暂停当前低优先级,待高优先级任务执行完之后,再继续执行或重新执行
1. useTransition
React 的状态更新可以分为两类:
- 紧急更新(Urgent updates):比如打字、点击、拖动等,需要立即响应的行为,如果不立即响应会给人很卡的感觉。
- 过渡更新(Transition updates):将 UI 从一个视图过渡到另一个视图。有些延迟,不立即相应是可以接受的。
并发模式只是提供了可中断的能力,默认情况下,所有的更新都是紧急更新。
所以它提供了 startTransition
让我们手动指定哪些更新是紧急的,哪些是非紧急的。
/*
* @作者: kerwin
*/
import React, { useState, useEffect, useTransition } from 'react';
function List(props) {
const [list, setList] = useState([]);
useEffect(() => {
setTimeout(()=>{
setList(new Array(5000).fill(""));
},100)
}, [props.search]);
return (
<ul>
{list.map((item, index) => (
<Item key={index} value={index+"_"+props.search}></Item>
))}
</ul>
);
}
function Item(props) {
return <li>
{props.value}
</li>
}
export default function App() {
const [search, setSearch] = useState("")
const [text, setText] = useState("")
const [isPending, startTransition] = useTransition();
return (
<div>
<input value={text} onChange={(evt) => {
setText(evt.target.value)
startTransition(()=>{
setSearch(evt.target.value)
})
}} /> {isPending && "等待..."}
<List search={search} />
</div>
)
}
2. useDeferredValue
这个方法返回一个延迟响应的值,可以让一个state
延迟生效,只有当前没有紧急更新时,该值才会变为最新值。useDeferredValue
和 startTransition
一样,都是标记了一次非紧急任务更新。
- 相同:
useDeferredValue
本质上和与useTransition
内部实现一样,都是标记成了延迟更新
任务。 - 不同:
useTransition
是把更新任务变成了延迟更新任务,而useDeferredValue
把一个状态变成延迟的状态。
export default function App() {
const [search, setSearch] = useState("")
const [text, setText] = useState("")
const [isPending, startTransition] = useTransition();
return (
<div>
<input value={text} onChange={(evt) => {
setText(evt.target.value)
setSearch(evt.target.value)
}} /> {isPending && "等待..."}
<List search={useDeferredValue(search)} />
</div>
)
}
五. 严格模式(muted colors)
六. Suspense组件的变化
React 18 的 Suspense 组件中,官方对 空的fallback 属性的处理方式做改变:不再跳过 缺失值 或 值为null 的 fallback 的 Suspense 边界。即使不写fallback, 也不会报错。
1. 版本17
<Suspense fallback={<Loading />}> // <--- this boundary is used
<Suspense> // <--- this boundary is skipped, no fallback
<Page />
</Suspense>
</Suspense>
2. 版本18
<Suspense fallback={<Loading />}> // <--- not used
<Suspense> // <--- this boundary is used, rendering null for the fallback
<Page />
</Suspense>
</Suspense>
Suspense源码
class Suspense extends React.Component {
state = { promise: null }
componentDidCatch(e) {
if (e instanceof Promise) {
this.setState(
{ promise: e }, () => {
e.then(() => {
this.setState({ promise: null })
})
})
}
}
render() {
const { fallback, children } = this.props
const { promise } = this.state
return <>
{ promise ? fallback : children }
</>
}
}
七. React 空组件的返回值
如果React返回一个空组件
,React17只允许返回null
。React18 也允许返回undefined.
function Animal({type}) {
if (type === 'cat') {
// Will error, missing return statement.
// This is always a mistake.
<Cat />;
}
// Will error, returns undefined.
// Did you mean to return nothing,
// or did you forget to return a default?
return;
}
八.组件卸载更新状态的警告删除
标签:千锋,const,18,更新,React,useState,return From: https://www.cnblogs.com/SanshQ/p/17973633组件已经卸载,此时并没有内存泄漏,因为已经被垃圾回收机制回收了,此时,警告具有误导性,所以删除了。