Skip to content

feat(reactotron-react-native): track Expo expo/fetch in the networking plugin#1613

Open
ShanavasPS wants to merge 1 commit into
infinitered:masterfrom
ShanavasPS:feat/expo-fetch-networking
Open

feat(reactotron-react-native): track Expo expo/fetch in the networking plugin#1613
ShanavasPS wants to merge 1 commit into
infinitered:masterfrom
ShanavasPS:feat/expo-fetch-networking

Conversation

@ShanavasPS

@ShanavasPS ShanavasPS commented Jun 9, 2026

Copy link
Copy Markdown

Please verify the following:

  • yarn build-and-test:local passes
  • I have added tests for any new features, if relevant
  • README.md (or relevant documentation) has been updated with your changes

Describe your PR

Closes #1612 .

Problem

Expo SDK 56 installs expo/fetch as the default globalThis.fetch. expo/fetch is backed by a native module and bypasses XMLHttpRequest, so the networking plugin's XHRInterceptor never sees it — on Expo SDK 56+ the plugin silently misses all fetch traffic.

(For context, the existing XHRInterceptor only covers React Native's XHR-backed fetch. The same blind spot affects other XHR-based network inspectors on Expo SDK 56+.)

Solution

Add a FetchInterceptor that mirrors XHRInterceptor's shape (set*Callback / enableInterception / disableInterception) and wraps the global fetch only when it is the expo/fetch builtin, detected via Symbol.for("expo.builtin"). React Native's XHR-backed fetch is left to XHRInterceptor, so there is no double-reporting. The networking plugin wires Reactotron into it in onConnect, gated by a new ignoreExpoFetch option.

Care was taken to keep this safe for expo/fetch's streaming model:

  • The wrapper returns the original Response immediately and reads the body off a clone, asynchronously — the caller is never blocked and streaming bodies stay intact.
  • text/event-stream (and the existing image content types) are never cloned/read, so streaming responses aren't buffered.
  • Request URL/method/header parsing for the Request/URL/string argument forms is handled in the interceptor; query-param parsing, content-type policy, and timing stay in the plugin (matching the XHR path).

Files

  • lib/reactotron-react-native/src/fetch-interceptor.ts — new, mechanism only (mirrors xhr-interceptor.ts)
  • lib/reactotron-react-native/src/fetch-interceptor.test.ts — unit tests (no-op off Expo, wrap/callbacks, rejection, no double-wrap, restore on disable)
  • lib/reactotron-react-native/src/plugins/networking.ts — wire in FetchInterceptor, add ignoreExpoFetch option
  • docs/plugins/networking.md — document expo/fetch support and ignoreExpoFetch

Notes / known limitations

  • Detection is by symbol, so it is a no-op on non-Expo runtimes and on SDKs where globalThis.fetch is not expo/fetch.
  • Only globalThis.fetch is wrapped. Code that does import { fetch } from 'expo/fetch' and captures the reference directly bypasses this (as it does the XHR interceptor); the global wrap covers the common case.
  • Interception is installed in onConnect, so requests fired before Reactotron connects aren't captured.

…g plugin

Expo SDK 54+ installs expo/fetch as the default globalThis.fetch. It is
backed by a native module and bypasses XMLHttpRequest, so XHRInterceptor
never sees it and the networking plugin silently misses all fetch traffic
on Expo.

Add a FetchInterceptor that mirrors XHRInterceptor (set*Callback /
enableInterception / disableInterception) and wraps the global fetch only
when it is the expo/fetch builtin (detected via Symbol.for("expo.builtin")).
RN's XHR-backed fetch is left to XHRInterceptor, so there is no double
reporting. The networking plugin wires Reactotron into it in onConnect,
gated by a new `ignoreExpoFetch` option.

The wrapper returns the original response immediately and reads the body
off a clone asynchronously, so callers are never blocked; image and
text/event-stream bodies are skipped so streaming responses are not
buffered.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Network requests not captured on Expo SDK 56

2 participants