跳至主要内容

关于新架构

信息

如果您正在寻找新架构指南,它们已移至 工作组.

自 2018 年以来,React Native 团队一直在重新设计 React Native 的核心内部结构,以使开发人员能够创建更高质量的体验。截至 2024 年,此版本的 React Native 已在规模上得到验证,并为 Meta 的生产应用程序提供支持。

术语新架构指的是新的框架架构以及将其开源的工作。

React Native 0.68开始,新架构已可供实验性选择加入,并在每个后续版本中不断改进。团队现在正致力于将其作为 React Native 开源生态系统的默认体验。

为什么需要新架构?

在使用 React Native 构建多年的过程中,团队发现了一系列限制,这些限制阻碍了开发者打造某些具有高品质的体验。这些限制是现有框架设计中的根本问题,因此新架构作为对 React Native 未来的一项投资而启动。

新架构解锁了在传统架构中无法实现的功能和改进。

同步布局和效果

构建自适应 UI 体验通常需要测量视图的大小和位置并调整布局。

目前,您将使用onLayout事件获取视图的布局信息并进行任何调整。但是,onLayout回调中的状态更新可能在绘制上一次渲染后应用。这意味着用户可能会看到中间状态或在渲染初始布局和响应布局测量之间出现视觉跳跃。

使用新架构,我们可以通过同步访问布局信息和正确安排更新来完全避免此问题,这样用户就看不到任何中间状态。

示例:渲染工具提示

在视图上方测量和放置工具提示可以让我们展示同步渲染解锁了什么。工具提示需要知道其目标视图的位置才能确定它应该渲染的位置。

在当前架构中,我们使用onLayout获取视图的测量结果,然后根据视图的位置更新工具提示的位置。

function ViewWithTooltip() {
// ...

// We get the layout information and pass to ToolTip to position itself
const onLayout = React.useCallback(event => {
targetRef.current?.measureInWindow((x, y, width, height) => {
// This state update is not guaranteed to run in the same commit
// This results in a visual "jump" as the ToolTip repositions itself
setTargetRect({x, y, width, height});
});
}, []);

return (
<>
<View ref={targetRef} onLayout={onLayout}>
<Text>Some content that renders a tooltip above</Text>
</View>
<Tooltip targetRect={targetRect} />
</>
);
}

使用新架构,我们可以使用useLayoutEffect在单个提交中同步测量和应用布局更新,避免视觉“跳跃”。

function ViewWithTooltip() {
// ...

useLayoutEffect(() => {
// The measurement and state update for `targetRect` happens in a single commit
// allowing ToolTip to position itself without intermediate paints
targetRef.current?.measureInWindow((x, y, width, height) => {
setTargetRect({x, y, width, height});
});
}, [setTargetRect]);

return (
<>
<View ref={targetRef}>
<Text>Some content that renders a tooltip above</Text>
</View>
<Tooltip targetRect={targetRect} />
</>
);
}
A view that is moving to the corners of the viewport and center with a tooltip rendered either above or below it. The tooltip is rendered after a short delay after the view moves
工具提示的异步测量和渲染。 查看代码.
A view that is moving to the corners of the viewport and center with a tooltip rendered either above or below it. The view and tooltip move in unison.
工具提示的同步测量和渲染。 查看代码.

并发渲染器和功能支持

新架构支持并发渲染以及在React 18及更高版本中发布的功能。现在,您可以在 React Native 代码中使用诸如 Suspense 用于数据获取、Transitions 以及其他新的 React API 等功能,进一步统一 Web 和原生 React 开发之间的代码库和概念。

并发渲染器还带来了开箱即用的改进,例如自动批处理,这减少了 React 中的重新渲染。

示例:自动批处理

使用新架构,您将获得 React 18 渲染器的自动批处理。

在此示例中,滑块指定要渲染的图块数量。将滑块从 0 拖动到 1000 将触发一系列快速的状态更新和重新渲染。

在比较相同代码的渲染器时,您可以直观地注意到渲染器提供了更流畅的 UI,并且中间 UI 更新更少。来自原生事件处理程序(如原生 Slider 组件)的状态更新现在已批处理。

A video demonstrating an app rendering many views according to a slider input. The slider value is adjusted from 0 to 1000 and the UI slowly catches up to rendering 1000 views.
使用旧版渲染器渲染频繁的状态更新。
A video demonstrating an app rendering many views according to a slider input. The slider value is adjusted from 0 to 1000 and the UI resolves to 1000 views faster than the previous example, without as many intermediate states.
使用 React 18 渲染器渲染频繁的状态更新。

新的并发功能,例如Transitions,赋予您表达 UI 更新优先级的能力。将更新标记为较低优先级告诉 React 它可以“中断”渲染更新以处理更高优先级的更新,以确保在重要的位置提供响应式用户体验。

示例:使用 startTransition

我们可以基于之前的示例来展示 Transitions 如何中断正在进行的渲染以处理更新的状态更新。

我们将图块数量状态更新用 startTransition 包裹,以指示渲染图块可以被中断。startTransition 还提供了一个 isPending 标志,用于告诉我们何时完成转换。

function TileSlider({value, onValueChange}) {
const [isPending, startTransition] = useTransition();

return (
<>
<View>
<Text>
Render {value} Tiles
</Text>
<ActivityIndicator animating={isPending} />
</View>
<Slider
value={1}
minimumValue={1}
maximumValue={1000}
step={1}
onValueChange={newValue => {
startTransition(() => {
onValueChange(newValue);
});
}}
/>
</>
);
}

function ManyTiles() {
const [value, setValue] = useState(1);
const tiles = generateTileViews(value);
return (
<TileSlider onValueChange={setValue} value={value} />
<View>
{tiles}
</View>
)
}

您会注意到,在转换中频繁更新的情况下,React 渲染的中间状态更少,因为它在状态变得陈旧后立即停止渲染状态。相比之下,在没有 Transitions 的情况下,会渲染更多中间状态。这两个示例都使用自动批处理。但是,Transitions 为开发人员提供了更多能力来批处理正在进行的渲染。

A video demonstrating an app rendering many views (tiles) according to a slider input. The views are rendered in batches as the slider is quickly adjusted from 0 to 1000. There are less batch renders in comparison to the next video.
使用 Transitions 渲染图块以中断正在进行的陈旧状态渲染。 查看代码.
A video demonstrating an app rendering many views (tiles) according to a slider input. The views are rendered in batches as the slider is quickly adjusted from 0 to 1000.
渲染瓦片而不将其标记为过渡。 查看代码.

快速 JavaScript/原生接口

新架构移除了 JavaScript 和原生之间 异步桥接,并用 JavaScript 接口 (JSI) 取代它。JSI 是一个接口,允许 JavaScript 持有对 C++ 对象的引用,反之亦然。通过内存引用,您可以直接调用方法,而无需序列化成本。

JSI 使 VisionCamera(一个流行的 React Native 相机库)能够实时处理帧。典型的帧缓冲区为 10 MB,根据帧速率,每秒大约相当于 1 GB 的数据。与桥接的序列化成本相比,JSI 可以轻松处理这种数量的接口数据。JSI 可以公开其他复杂的基于实例的类型,例如数据库、图像、音频样本等。

新架构中对 JSI 的采用消除了所有原生-JavaScript 交互中这类序列化工作。这包括初始化和重新渲染原生核心组件,例如 ViewText。您可以在新架构中阅读有关我们 渲染性能调查 的更多信息,以及我们测量的改进基准。

了解更多

为了实现这一点,新架构必须重构 React Native 基础设施的多个部分。要了解有关重构及其带来的其他好处的更多信息,请查看新架构工作组的 文档

启用新架构后我该期待什么?

虽然新架构启用了这些功能和改进,但为您的应用程序或库启用新架构可能不会立即提高性能或用户体验。

例如,您的代码可能需要重构以利用新的功能,例如同步布局效果或并发功能。虽然 JSI 会最大程度地减少 JavaScript 和原生内存之间的开销,但数据序列化可能不是您应用程序性能的瓶颈。

在您的应用程序或库中启用新架构意味着选择 React Native 的未来。

该团队正在积极研究和开发新架构解锁的新功能。例如,Web 对齐是 Meta 正在积极探索的一个领域,并将发布到 React Native 开源生态系统。

您可以在我们专门的 讨论和提案 存储库中关注并做出贡献。

我应该现在使用新架构吗?

目前,新架构被认为是实验性的,我们仍在继续完善向后兼容性,以提供更好的采用体验。

团队计划在 2024 年底之前发布的 React Native 版本中默认启用新架构。

我们的建议如下

  • 对于大多数生产应用程序,我们建议您现在启用新架构。等待官方发布将提供最佳体验。
  • 如果您维护 React Native 库,我们建议您启用它并验证您的用例是否涵盖。您可以在 此处 找到说明。

启用新架构

如果您有兴趣试用新架构体验,您可以在我们专门的工作组中找到 说明新架构工作组 是一个专门的空间,用于支持和协调新架构的采用,团队会在那里发布定期更新。