Repository navigation
fix(tracing): Support Expo Router 58 in expoRouterIntegration #6923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d1e127f
c899efa
fc6a0b5
0e409bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,7 @@ | |
|
|
||
| - Find `ios/.xcode.env` in the Expo plugin "Upload Debug Symbols to Sentry" phase when the iOS project uses Swift Package Manager instead of CocoaPods ([#6911](https://github.com/getsentry/sentry-react-native/pull/6911)) | ||
| - Fix HTTP timing listeners leaking on React Native below 0.83 and when `expo/fetch` is detected, and respect the `enableHTTPTimings` option ([#6912](https://github.com/getsentry/sentry-react-native/pull/6912)) | ||
| - Support Expo Router 58 in `expoRouterIntegration`. Metro no longer warns about the removed `expo-router/build/global-state/router-store` module, and the integration creates navigation spans again ([#6923](https://github.com/getsentry/sentry-react-native/pull/6923)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is accurate for v58. If dropping older Expo Router versions is intentional, it's a breaking change and the entry should say so. Otherwise it goes away once the two blockers are fixed. |
||
| - Remove the `@sentry/browser` feedback modules and the server-only `@sentry/core` modules from native bundles built on Windows. Before this fix, `includeWebFeedback: false` made these bundles fail at launch ([#6915](https://github.com/getsentry/sentry-react-native/pull/6915)) | ||
| - Stop wrapping the SDK's own `RNSentry` module in `turboModuleContextIntegration` by default. Each wrapped call wrote to the native scope several times, which added CPU time to every SDK call on iOS ([#6921](https://github.com/getsentry/sentry-react-native/pull/6921)) | ||
| - To wrap `RNSentry` again, add `{ name: 'RNSentry' }` to the `modules` option. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
|
|
||
| export interface ExpoRouterNavigationRef { | ||
| current: unknown | null; | ||
| getRootState?: () => unknown; | ||
| } | ||
|
|
||
| export interface ExpoRouterUrlObject { | ||
|
|
@@ -22,7 +23,7 @@ export interface ExpoRouterUrlObject { | |
|
|
||
| export interface ExpoRouterStore { | ||
| navigationRef?: ExpoRouterNavigationRef; | ||
| getRouteInfo?: () => ExpoRouterUrlObject; | ||
| getRouteInfo?: () => ExpoRouterUrlObject | undefined; | ||
| } | ||
|
|
||
| export interface NormalizedExpoRouterRouteInfo { | ||
|
|
@@ -42,17 +43,67 @@ export interface NormalizedExpoRouterRouteInfo { | |
| segments?: string[]; | ||
| } | ||
|
|
||
| export interface ExpoRouterActionDispatchedEvent { | ||
| actionType?: string; | ||
| payload?: unknown; | ||
| } | ||
|
|
||
| export interface ExpoRouterInternalNavigationEvents { | ||
| addListener: ( | ||
| name: 'actionDispatched', | ||
| callback: (event: ExpoRouterActionDispatchedEvent) => void, | ||
| ) => (() => void) | undefined; | ||
| } | ||
|
|
||
| /** | ||
| * Returns Expo Router's internal router store, or `null` if `expo-router` is | ||
| * not installed or the build does not expose the expected module path. | ||
| * Returns the navigation container ref and route info of Expo Router, or `null` | ||
| * if `expo-router` is not installed or does not expose the expected API. | ||
| * | ||
| * Only module paths that exist in every supported Expo Router version are | ||
| * required here. Expo Router 58 declares `exports`, so Metro warns about any | ||
| * deep path that is missing from the installed version. | ||
| */ | ||
| export function tryGetExpoRouterStore(): ExpoRouterStore | null { | ||
| try { | ||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
| const mod = require('expo-router/build/global-state/router-store') as { | ||
| store?: ExpoRouterStore; | ||
| const expoRouter = require('expo-router') as { | ||
| useNavigationContainerRef?: () => ExpoRouterNavigationRef | undefined; | ||
| }; | ||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
| const routeInfoModule = require('expo-router/build/global-state/getRouteInfoFromState') as { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocker: this breaks Expo Router ≤55. Suggestion: treat route info as optional. When it's missing, still register the container and skip the route override. Going back to |
||
| getRouteInfoFromState?: (state: unknown) => ExpoRouterUrlObject; | ||
| }; | ||
| // Not a React hook: it returns a module-level ref in Expo Router 57 and 58. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: this is only true for v58 ( |
||
| const getNavigationContainerRef = expoRouter?.useNavigationContainerRef; | ||
| const getRouteInfoFromState = routeInfoModule?.getRouteInfoFromState; | ||
| if (!getNavigationContainerRef || !getRouteInfoFromState) { | ||
| return null; | ||
| } | ||
| const navigationRef = getNavigationContainerRef(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocker: this regresses #6431 on v56/57. The ref is read once here, and Suggestion: call |
||
| return { | ||
| navigationRef, | ||
| getRouteInfo: () => { | ||
| const state = navigationRef?.current ? navigationRef.getRootState?.() : undefined; | ||
| return state ? getRouteInfoFromState(state) : undefined; | ||
| }, | ||
| }; | ||
| } catch { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Returns the internal navigation event emitter of Expo Router 58 and later, or | ||
| * `null` for older versions. Expo Router 58 does not emit React Navigation's | ||
| * `__unsafe_action__` event, so this is the only signal of a dispatched action. | ||
| */ | ||
| export function tryGetExpoRouterNavigationEvents(): ExpoRouterInternalNavigationEvents | null { | ||
| try { | ||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
| const mod = require('expo-router/build/global-state/internalNavigationEvents') as { | ||
| internalNavigationEvents?: ExpoRouterInternalNavigationEvents; | ||
| }; | ||
| return mod?.store ?? null; | ||
| return mod?.internalNavigationEvents ?? null; | ||
|
alwx marked this conversation as resolved.
|
||
| } catch { | ||
| return null; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## 8.32.0.Consider moving the entry to the
## Unreleasedsection, please.