This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

React Navigation 集成

通过启用 EAS Observe 的 React Navigation 集成来跟踪每个屏幕的渲染和交互时间。


EAS Observe 是一个用于 React Navigation 的可选择集成,它会收集每个屏幕的指标,并用屏幕的路由名称路径(例如 /Tabs/Sessions)进行标记。这使你可以在仪表板中按屏幕比较导航性能,而不仅仅查看应用范围的汇总数据。

🌐 EAS Observe ships an opt-in integration for React Navigation that collects per-screen metrics tagged with the screen's route-name path (for example, /Tabs/Sessions). This lets you compare navigation performance by screen in the dashboard instead of looking only at app-wide aggregates.

如果你的应用使用 Expo Router,请改用 Expo Router 集成。此页面适用于直接使用 React Navigation 的应用。

🌐 If your app uses Expo Router, use the Expo Router integration instead. This page is for apps that use React Navigation directly.

先决条件

🌐 Prerequisites

先决条件

3 要求

1.

Expo SDK 56 及更高版本

React Navigation 集成适用于 SDK 56 及更高版本。在较早的 SDK 中,expo-observe 仍会跟踪全应用的指标,但不会发出每个屏幕的导航事件。

2.

一个已经使用 EAS 观察的应用

按照 入门指南 安装 expo-observe 并创建你的第一个构建。

3.

在应用中安装了 @react-navigation/native 7 或更高版本

该集成在运行时依赖 @react-navigation/native(v7.0.0 或更高版本)。如果未安装该包,集成将静默不做任何操作。

1

启用集成

🌐 Enable the integration

警告 集成必须在挂载前启用,且不能在运行时切换。在应用挂载后调用 configure(),或在会话中途切换标志,会抛出错误。

在任何屏幕挂载之前,在模块作用域内使用 react-navigation 集成标志调用 Observe.configure()

🌐 Call Observe.configure() with the react-navigation integration flag at module scope, before any screen mounts:

App.tsx
import { Observe } from 'expo-observe'; Observe.configure({ integrations: { 'react-navigation': true }, });

2

将集成连接到你的导航

🌐 Connect the integration to your navigation

你如何连接集成取决于你的应用是否使用 React Navigation 的动态或静态配置。这两种方法都会记录相同的每个屏幕的指标。

🌐 How you connect the integration depends on whether your app uses React Navigation's dynamic or static configuration. Both approaches record the same per-screen metrics.

对于动态配置,将你的顶层 <NavigationContainer> 替换为 <ObserveNavigationContainer>。它封装了原生容器,接受相同的属性,并转发相同的引用。它还会订阅导航状态变化,因此可以记录每个屏幕的渲染时间。

🌐 For dynamic configuration, replace your top-level <NavigationContainer> with <ObserveNavigationContainer>. It wraps the stock container, accepts the same props, and forwards the same ref. It also subscribes to navigation state changes so it can record per-screen render timings.

App.tsx
import { Observe } from 'expo-observe'; import { ObserveNavigationContainer } from 'expo-observe/integrations/react-navigation'; Observe.configure({ integrations: { 'react-navigation': true }, }); export default function App() { return <ObserveNavigationContainer>{/* your navigators */}</ObserveNavigationContainer>; }

3

在你的屏幕中调用 useObserve()

🌐 Call useObserve() in your screens

使用 useObserve() 钩子获取一个自动作用于当前屏幕的 markInteractive。发出的事件会附上屏幕的路径标签。

🌐 Use the useObserve() hook to get a markInteractive that is automatically scoped to the current screen. The emitted event is tagged with the screen's path.

screens/Home.tsx
import { useObserve } from 'expo-observe'; import { useEffect } from 'react'; export default function Home() { const { markInteractive } = useObserve(); useEffect(() => { markInteractive(); }, [markInteractive]); return (/* your screen content */); }

信息 如果集成被禁用或未安装 @react-navigation/nativeuseObserve() 将回退到全局 AppMetrics.markInteractive。无论集成状态如何,你都可以保留该钩子。

指标

🌐 Metrics

每屏首次渲染(cold_ttr

🌐 Per-screen first render (cold_ttr)

它衡量的内容: 从导航操作被触发(例如,navigation.navigate())到目标屏幕首次获得焦点的时间。对于应用启动后的首次焦点,测量时间从 JS 包加载时开始,事件中包含 isAppLaunch: true

在一次会话中的每个屏幕实例最多发出一次。

🌐 Emitted at most once per screen instance within a session.

事件参数:

参数类型描述
routeNamestring路由名称路径(例如,/Tabs/Sessions)。
routeParamsobject关注的路由参数(例如,{ sessionId: 'abc' })。
isAppLaunchboolean相对于进程启动时测量的 true,后续导航的 false

每屏幕预热渲染(warm_ttr

🌐 Per-screen warm render (warm_ttr)

测量内容:cold_ttr 相同,但针对那些在获取焦点前已经渲染的屏幕,通常是因为它们被预加载或用户返回到这些屏幕。仅当 Tab 导航器的同级页面被挂载后,它们才计为热屏。使用 React Navigation v7 默认的 lazy: true 时,未聚焦的标签页保持未挂载状态,其第一次获取焦点会记录为 cold_ttr

事件参数:

参数类型描述
routeNamestring路由名称路径(例如,/Tabs/Sessions)。
routeParamsobject聚焦的路由参数(例如,{ sessionId: 'abc' })。

每屏到交互时间(tti

🌐 Per-screen time to interactive (tti)

它测量的内容: 从导航操作被分发到目标屏幕上调用 markInteractive() 的时间。每次导航只记录第一次调用,因此可以安全地多次调用 markInteractive()

事件参数:

参数类型描述
routeNamestring路由名称路径(例如,/Tabs/Sessions)。
routeParamsobject关注的路由参数。
...any通过 markInteractive({ ... }) 传递的任何自定义参数。

注意事项与故障排除

🌐 Notes and troubleshooting

  • routeName 是由路由名称(/Tabs/Sessions)构建的,因此路由参数从不出现在路径中。这可以使指标在不同的参数值下保持稳定,从而仪表板会将它们归类在一起。参数值仍然可以通过 routeParams 在事件中获得。
  • 该集成仅在运行时安装了 @react-navigation/native 时才会激活。如果未安装,useObserve() 仍然可以正常工作,但不会发出每屏导航指标。在没有 @react-navigation/native 的情况下渲染 <ObserveNavigationContainer><ObserveNavigationProvider> 会抛出错误。
  • 在通过 Observe.configure({ integrations: { 'react-navigation': true } }) 挂载之前必须启用该集成。在应用挂载之后,或在 <ObserveNavigationContainer><ObserveNavigationProvider> 挂载之后切换它,会抛出错误。
  • 在静态配置下,将相同的 ref 传递给 <ObserveNavigationProvider><Navigation> 元素。如果提供者收到的 ref 未连接到导航容器,则不会发出每个屏幕的指标。
  • markInteractive() 仅在屏幕获得焦点时记录一次。在未获得焦点的屏幕上进行的调用会更新内部状态,但在屏幕获得焦点之前不会触发 tti 事件。
  • 在屏幕组件内部调用 useObserve(),而不是在更高级别的封装器中。如果屏幕的身份在渲染之间发生变化,该钩子会记录一个警告。如果 markInteractive() 记录了 Calling markInteractive on unmounted screenNo metadata available for the current screen,说明调用发生在屏幕组件外部或卸载之后。将调用移到屏幕组件内部的 useEffect 中。
  • 有关 EAS Observe 的一般问题,请参阅 故障排除