React 18 Alpha 以及来了,并无像 React 17 没有更新不少新特性,V18 做为 React 的下一个大版本将关注点放在了并发模式上也就是谈论了好久的(Concurrent Mode)javascript
那么究竟都将有哪些新特性,下面让咱们一块儿来看一看。css
npm install react@alpha react-dom@alpha
复制代码
以前的使用中都是经过 ReactDom.render 将应用组件渲染到页面的根元素html
ReactDOM.render(<APP/>,document.getElementById( root ))
复制代码
React 18 提供了新的方法 经过 ReactDom.creatRoot 建立根节点对象,在经过根节点对象进行渲染。java
(使用 CodeSandBox 进行测试)react
// index.js
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import App from "./App";
const rootElement = document.getElementById("root");
const root = ReactDOM.createRoot(rootElement);
root.render(
<StrictMode> <App />{" "} </StrictMode>
);
复制代码
在React 17及更早版本中,当浏览器事件触发组件批量状态更新从而渲染更新时,React 不会自动将组件批量从新渲染。git
可是若是使用上面提到的 V18 新 Root API,则全部状态更新都将在发生时自动批量重渲染。github
若是某些关键组件不想被自动更新可使用 ReactDOM.flushSync() 退出操做npm
import { flushSync } from 'react-dom'; // Note: react-dom, not react
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React has updated the DOM by now
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM by now
}
复制代码
React 18 的更新后全面支持 Suspense ,顾名思义将暂时闲置的组件搁置起来,实现懒加载。浏览器
import "./styles.css";
import { useEffect, useState, useLayoutEffect, Suspense } from "react";
import { fetchProfileData } from "./fakeApi";
const initialResource = fetchProfileData();
function ProfilePage() {
const [resource, setResource] = useState(initialResource);
return (
<> <Suspense fallback={ <> <h1>Loading profile...</h1> </> } > <Sibling name="one" /> <ProfileDetails resource={resource} /> <Suspense fallback={<h1>Loading posts...</h1>}> <Sibling name="two" /> <ProfileTimeline resource={resource} /> <Sibling name="three" /> </Suspense> <Sibling name="four" /> </Suspense> </>
);
}
function Sibling({ name }) {
useLayoutEffect(() => {
console.log("Layout effect Sibling", name);
return () => {
console.log("Layout cleanup Sibling", name);
};
});
useEffect(() => {
console.log("Effect Sibling", name);
return () => {
console.log("Cleanup Sibling", name);
};
}, [name]);
console.log("Render sibling", name);
return <h1>Sibling</h1>;
}
function ProfileDetails({ resource }) {
useLayoutEffect(() => {
console.log("Layout effect ProfileDetails");
return () => {
console.log("Layout cleanup ProfileDetails");
};
});
useEffect(() => {
console.log("Effect ProfileDetails");
return () => {
console.log("Cleanup ProfileDetails");
};
});
const user = resource.user.read();
return <h1>{user.name}</h1>;
}
function ProfileTimeline({ resource }) {
const posts = resource.posts.read();
useLayoutEffect(() => {
console.log("Layout effect ProfileTimeline");
return () => {
console.log("Layout cleanup ProfileTimeline");
};
});
useEffect(() => {
console.log("Effect ProfileTimeline");
return () => {
console.log("Cleanup ProfileTimeline");
};
});
return (
<ul> {posts.map((post) => ( <li key={post.id}>{post.text}</li> ))} </ul>
);
}
export default ProfilePage;
复制代码
当数据未加载完成,显示 Loading 组件,加载后显示完整组件。markdown
代码源于romantic-architecture-ht3qi
关于 Suspense API 也还没有稳定,不建议使用在生产环境
Suspense List 为 Concurrent Mode 中的提案 reactjs.org/docs/concur…
Suspense List 做为 Suspense 的容器组件经过编排这些组件向用户显示的顺序,帮助协调许多能够挂起的组件。
<SuspenseList revealOrder="forwards">
<Suspense fallback={'Loading...'}> <ProfilePicture id={1} /> </Suspense>
<Suspense fallback={'Loading...'}> <ProfilePicture id={2} /> </Suspense>
<Suspense fallback={'Loading...'}> <ProfilePicture id={3} /> </Suspense>
...
</SuspenseList>
复制代码
revealOrder (forwards, backwards, together) 定义了 SuspenseList 子组件应该显示的顺序。
tail (collapsed, hidden) 指定如何显示 SuspenseList 中未加载的项目。
默认状况下,SuspenseList 将显示列表中的全部 fallback。
collapsed 仅显示列表中下一个 fallback。hidden 未加载的项目不显示任何信息。
请注意,SuspenseList 只对其下方最近的 Suspense 和 SuspenseList 组件进行操做。它不会搜索深度超过一级的边界。不过,能够将多个 SuspenseList 组件相互嵌套来构建栅格。
这是 V18 引入的新 API,这有助于保持当前的网页响应,而且可以同时进行计算量大复杂度高的的非阻塞UI更新。 之前咱们可能会本身去加一些防抖这样的操做去人为的延迟过滤数据的计算和渲染。新的 startTransition API 可让咱们把响应数据标记成 transitions 状态延迟处理。
官方工做组两个应用场景提出了:
startTransition API 可让开发者显式的指定那个UI渲染的优先级更高,哪些须要实时更新哪些须要延迟更新
(使用 CodeSandBox 进行测试)
// APP.js
import "./styles.css";
import { useState, startTransition } from "react";
export default function App() {
let [value, setValue] = useState(0);
const onChange = (event) => {
startTransition(() => {
setValue(event.target.value);
console.log(event.target.value);
});
};
return (
<div className="App"> <input value={value} onChange={onChange} /> <div>{value}</div> </div>
);
}
复制代码
全部在 startTransition 回调中的更新都会被认为是非紧急处理,若是出现更紧急的更新(好比用户又输入了新的值),则上面的更新都会被中断,直到没有其余紧急操做以后才会去继续执行更新。
实际测试时发现好像对于中文输入法不是特别友好但目前没有找到合适的解决方案。
useDeferredValue 容许变量延迟更新, API 还未稳定,当前用法为
import "./styles.css";
import { useState, useDeferredValue } from "react";
export default function App() {
let [value, setValue] = useState(0);
const deferredValue = useDeferredValue(value, { timeoutMs: 2000 });
return (
<div className="App"> <div>{deferredValue}</div> <button onClick={()=>{setValue(deferredValue+1)}}>click me</button> </div>
);
}
复制代码
React 18 发布计划 React 18 官方介绍(github.com/reactwg/rea… API useDeferredValue、 还没 released ,咱们下次再用,下面是 React 18 的发布时间表:
参考连接: