WordPress 6.2 附带React 18 版,这是用于构建块编辑器和所有自定义块的JavaScript库。它具有多项新功能、改进和错误修复,包括一种称为并发模式的新渲染算法。( #45235 )
在并发模式下,React 可以更快地执行UI更新,并保持网页响应。当它处理大型复杂的 UI 更新时,它仍然可以实时处理所有用户输入(鼠标事件、滚动、键盘事件),同时处理它已经在做的工作。
但是,它也引入了一些开发人员需要注意的潜在陷阱,并且可能会破坏一些依赖于事件和状态更新的精确计时的组件。这些陷阱只会影响一小部分复杂且专门的 React 代码。除非您的代码依赖于状态更新的特定时间,否则几乎可以肯定您的代码将继续工作而无需任何更改。
批量状态更新
几乎所有并发模式的陷阱都与称为“批量状态更新”的特性有关。这意味着什么?考虑这个 React 组件:
function ShowX() { const [ x, setX ] = useState( 0 ); console.log( 'rendering with state' , x ); useEffect( () => { const handle = setTimeout( () => { console.log( 'started setting state' ); setX( 1 ); setX( 2 ); console.log( 'finished setting state' ); }, 1000 ); return () => clearTimeout( handle ); }, [] ); return <div>{ x }</div>; } |
该组件最初将使用 进行渲染state 0
,一秒钟后它将依次进行两次状态更新:先是 to 1
,然后是 to 2
。在 React 17 中,没有并发模式和自动批处理,控制台中的消息将按以下顺序记录:
rendering with state 0 started setting state rendering with state 1 rendering with state 2 finished setting state |
每个 setX 调用都会立即同步触发一次组件渲染,并且会有两次渲染。当脚本执行 logs 行时finished setting state
,两个渲染都已经发生。更新的效果setX(1)
也已执行。每隔一段时间就会有一些代码依赖于渲染和/或效果此时已经执行的事实。而正是这种代码是并发模式错误的典型来源。因为在并发模式下,在 React 18 中,记录消息的顺序会有很大的不同:
rendering with state 0 started setting state finished setting state rendering with state 2 |
首先,当finished setting state
消息被记录时,还没有渲染发生。那个时候只是预定,还没有执行。
其次,两个setX(1)
更新setX(2)
都被批处理在一起,并且在批处理两个状态更新之后,只用两个最终值执行了一次渲染。这是错误的另一个来源。如果您的代码依赖于正在执行状态的渲染1
,那么它永远不会发生。效果也只与2
值一起运行,1
效果被跳过。
批量更新和@wordpress/data
批量状态更新的一个特例,通常出现在 WordPress 代码中,是@wordpress/data
商店中的调度调用:
const counter = useDispatch( counterStore ); counter.increment(); |
在这里,分派increment
操作最终会导致组件内部的状态更新,该组件从counterStore
. 有时,您的代码可以依赖这样一个事实,即在调用之后counter.increment()
,所有更新和重新呈现都已同步执行。但是,如上所述,在 React 18 并发模式下,这不会立即发生。更新只是在那个时候安排的。
用于挂载根的新API
如果您的插件或块将其自己的 React UI 安装到页面中,而不是导出 React 组件以由块编辑器呈现,您应该了解用于安装组件根的新 React 18 API。旧的 React 17 方式是render
函数 from react-dom
或 from @wordpress/element
:
import { render } from '@wordpress/element' ; const el = document.getElementById( 'root' ); render( <App />, el ); |
这仍然继续有效,您可以继续使用它。唯一的缺点是您会收到有关使用 React 17 遗留 API 的控制台警告,并且在以这种方式安装的 React 应用程序中禁用并发模式。
React 18 的方式是使用新的createRoot
API:
import { createRoot } from '@wordpress/element' ; const el = document.getElementById( 'root' ); const root = createRoot( el ); root.render( <App /> ); |
还有一个额外的步骤:从 DOM 元素创建一个根,然后将 JSX 元素渲染到该根中。以这种方式安装的应用程序将使用新的并发模式。
还有一个用于卸载 React 根目录的新 API。旧的是unmountComponentAtNode( el )
,新的是在根对象上调用一个方法:root.unmount()
React 18 中的其他新 API
React 18 中还有其他新的 API 函数,它们也都是由@wordpress/element
包导出的:
<a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-element/#usedeferredvalue">useDeferredValue</a>
<a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-element/#useid">useId</a>
<a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-element/#useinsertioneffect">useInsertionEffect</a>
<a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-element/#usesyncexternalstore">useSyncExternalStore</a>
<a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-element/#usetransition">useTransition</a>
<a href="https://developer.wordpress.org/block-editor/reference-guides/packages/packages-element/#starttransition">startTransition</a>
这些都是全新的,不会引入任何向后兼容性问题。如果您想了解或使用它们,请参阅React 18 迁移指南和React 文档。