Contents
自从 React v16
首次发布以来已经过去了大约三年的时间,等待下一个主要版本的发布已经结束了。React
团队承诺 v17
版本的发布对未来非常重要,但也提到没有添加新特性。你可能想知道它为什么会被发布。
在本文中,我将列出最新版本中所做的更改。
React 17
主要专注于使 React
本身更容易升级。尽管在这次更新中没有直接面向开发人员的功能是很不寻常的,但这次发布的主要目标是确保将一个版本的React管理的树嵌入到另一个版本的React管理的树中是安全的。React
开发人员团队将此称为“垫脚石”版本。https://reactjs.org/blog/2020/08/10/react-v17-rc.html
这些年来,React
升级要么全有要么全无。您要么必须继续使用旧版本,要么需要将整个应用程序升级到新版本。因此,如果新更新中引入了重大更改,并且您打算迁移到新版本,则必须更改代码库,尤其是在代码库很大的情况下。
React
团队已使用React 17
解决了这些问题中的大多数问题。当 React v18
和以下版本推出时,您可以通过升级应用程序的某些部分来逐步迁移,同时仍然让其他部分在 React v17
上运行。因此,如果您的大型应用程序使用的版本未得到积极维护,则此选项将非常有用。
React
的团队已经准备了一个仓库来演示如何延迟加载旧版本的 React
:
https://github.com/reactjs/react-gradual-upgrade-demo/
“在React 17中,React将不再在该document级别附加事件处理程序。而是将它们附加到根树容器中,以生成您的React树。https://reactjs.org/blog/2020/10/20/react-v17.html
让我们看一个例子。考虑将onClick事件附加到React中的按钮,如下所示:
<button onClick = {handleClick}>
与上面的代码等效的原始JS看起来像这样:
myButton.addEventListener('click',handleClick);
然后,React
将每种事件类型的一个处理程序直接附加到文档节点,而不是将其附加到声明它们的 DOM
节点。这称为事件委托。
在 React v17
中,事件处理程序将不再附加在文档级别,而是将它们附加到呈现树的 DOM
容器中。
const rootNode = document.getElementById('root');
ReactDOM.render(<App />,rootNode);
通过 React v17
的这一更改,现在可以安全嵌套使用不同版本的 React
构建的应用程序。
尽管升级到此新转换完全是可选的,但 React v17
提供了新的 JSX Transform
重写版本。它仍然提供一些好处,例如:
React
如果您想阅读更多有关此新转换的信息,请查看React团队的这篇博客文章:https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
此新版本附带一些重大更改。
如上所述,升级后可能会遇到一些问题。
在此新版本中,event.stopPropagation()
实际上会阻止你的文档处理程序释放
document.addEventListener('click', function() {
//此自定义处理程序将不再
//来自调用e.stopPropagation()的React组件的点击
});
要解决此问题,请 capture
通过将 { capture: true }
选项作为第三个参数传递,将事件侦听器转换为使用阶段,如下所示:
document.addEventListener('click',function(){
//现在此事件处理程序使用捕获阶段,
//因此它接收下面的* all * click事件!
},{capture:true});
这样,我们看到事件委托现在比以往任何时候都更接近正常的 DOM
。
React
对事件系统进行了一些更改:
onScroll
事件不再产生冒泡onBlur
和 onFocus
事件现在已经切换到使用本地 focusin
和 focusout
内部事件,更好地匹配 React
现有的行为,甚至提供更多的信息。onClickCapture
现在利用实际的浏览器捕获阶段侦听器。在这个版本中,事件池优化已经从 React
中删除,这是由于它非常混乱以及并没有提高性能
function handleChange(e) {
setData(data => ({
...data,
// This crashes in React 16 and earlier:
text: e.target.value
}));
}
在 React 17
中,此代码可以按您期望的那样工作。旧的事件池优化已被完全删除,因此您可以在需要时阅读事件字段
这个新版本还使 useEffect
钩子清理函数的定时更加一致
useEffect(() => {
// This is the effect itself.
return () => {
// This is its cleanup.
};
});
在 React v16
版本中,Effect
清理是同步操作,根据 React
博客的说法,在 React v17
中,Effect
清除功能始终异步运行。例如,如果要卸载组件,则在更新屏幕后运行清除。
undefined
返回一致的错误这句话怎么解释呢,在 React v16
中,返回 undefined
的函数总是会抛出错误,这主要是因为经常无意中造成返回 undefined
如:
function Button(){
//我们忘记写return,因此该组件返回undefined。
// React将其表面化为错误而不是忽略它。
<button />;
}
最初,这种行为只适用于类和函数组件,但是在新版本中,forwardRef
memo
组件也加入了这个功能,使它们的行为与常规的类和函数组件一致,请注意,如果您故意不进行任何渲染,该实例将返回 null
尽管 React v17
没有提供任何新功能,但它通过直接解决升级体验,并使 React
的行为更接近现代浏览器,为即将到来的版本奠定了坚实的基础
本文翻译自 What’s New in React v17?