React 18 这次是真的来了

百家 作者:程序员的那些事 2022-03-24 12:40:50

3月8日 React 官方发布了 「How to Upgrade to the React 18 Release Candidate[1]」 文章。文中提到了 RC 版本已经发布以及如何升级到新版本的指南。

根据 React 官方去年发布的计划来看,发布 RC 版本也就意味着正式版马上就要来了,大概延迟 2 ~ 4 周。

本文会着重介绍一些指南中和大家息息相关的点以及 React 18 有什么好用的新特性,如果你想了解更详细内容的话还是推荐各位自行阅读官方文章。

如何安装新版本

安装新版本需要大家指定为 rc 版本。

yarn?add?react@rc?react-dom@rc

有哪些常见 API 的变动

首先?ReactDOM.render?这个 API 在新版本中不被支持了,需要我们修改为如下代码:

//?Before
import?{?render?}?from?'react-dom';
const?container?=?document.getElementById('app');
render(<App?tab="home"?/>,?container);

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

这个代码变更应该是每个项目都得做的。另外?createRoot?还会将整个应用变成并发模式(concurrent mode),后面笔者会聊到这块。

其它还有一些别的改动,比如?unmountComponentAtNode?变成了?root.unmount

//?Before
unmountComponentAtNode(container);

//?After
root.unmount();

删除了?render?函数的回调:

//?Before
const?container?=?document.getElementById('app');
ReactDOM.render(<App?tab="home"?/>,?container,?()?=>?{
??console.log('rendered');
});

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

return?<App?tab="home"?/>
}

const?container?=?document.getElementById('app');
const?root?=?ReactDOM.createRoot(container);
root.render(<AppWithCallbackAfterRender?/>);

还有水合(hydrate)相关的变更,也就是 SSR 层面的:

//?Before
import?{?hydrate?}?from?'react-dom';
const?container?=?document.getElementById('app');
hydrate(<App?tab="home"?/>,?container);

//?After
import?{?hydrateRoot?}?from?'react-dom/client';
const?container?=?document.getElementById('app');
const?root?=?hydrateRoot(container,?<App?tab="home"?/>);
//?Unlike?with?createRoot,?you?don't?need?a?separate?root.render()?call?here.

SSR 相关的除了这个变更之外还有一些别的内容,比如 API 的新增、废弃及限制,对这方面关心的读者可以自行阅读?文章[2]

好用的新特性

首先是批量更新的优化。这个功能是帮助做性能优化的,可以将多次状态变更整合到一次,这样只需触发一次 UI 渲染,但是在 React 18 之前这个功能只适用于事件处理中。

如今在新版本中,无论状态更新在写在定时器、Promise 还是原生事件中,批量更新都会被触发。

//?Before?React?18?

function?handleClick()?{
??setCount(c?=>?c?+?1);
??setFlag(f?=>?!f);
??//?更新?UI?一次
}

setTimeout(()?=>?{
??setCount(c?=>?c?+?1);
??setFlag(f?=>?!f);
??//?更新?UI?两次
},?1000);

//?After?React?18?

function?handleClick()?{
??setCount(c?=>?c?+?1);
??setFlag(f?=>?!f);
??//?更新?UI?一次
}

setTimeout(()?=>?{
??setCount(c?=>?c?+?1);
??setFlag(f?=>?!f);
??//?更新?UI?一次
},?1000);

最后一个是和并发模式相关的内容,我们终于可以手动调节更新优先级了!

先简单介绍下优先级相关的东西,这个其实和 React 的调度息息相关。调度的时候内部会将不同的更新设置为不同的优先级,优先级高的更快执行,优先级低的更新可以被更高优先级所打断从而实现延后更新。

因此我们可以通过这个机制去调节某些状态更新被触发的时机,从而使别的更新更快被触发,也就是 UI 渲染的更及时。

那么我们如何手动调节呢?其实很简单:

import?{?startTransition?}?from?"react"

startTransition(()?=>?{
??//?状态更新
})


引用链接

[1]?How to Upgrade to the React 18 Release Candidate:?https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
[2]?文章:?https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-server-rendering-apis

- EOF -

推荐阅读??点击标题可跳转

1、从前,有两个卖水果的公司……

2、因为爬虫失控,CTO 和程序员双双被判刑

3、如果美国把根域名服务器封了,中国会从网络上消失吗?


关注「程序员的那些事」加星标,不错过圈内事

点赞和在看就是最大的支持?

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接