Tracking Touch Events

Learn more about how to enable tracking touch events.

Use version 1.5.0 or later to track touch events with Sentry's React Native SDK. You will also need to wrap your app with a TouchEventBoundary.

At the root of your app, usually App.js, wrap the app component with Sentry.TouchEventBoundary:

Copied
import * as Sentry from "@sentry/react-native";

const App = () => {
  return (
    <Sentry.TouchEventBoundary>
      <RestOfTheApp />
    </Sentry.TouchEventBoundary>
  );
};

export default AppRegistry.registerComponent(
  "Your Amazing App",
  () => App,
);

At the root of your app, usually App.js, wrap the app component with Sentry.withTouchEventBoundary:

Copied
import * as Sentry from "@sentry/react-native";

const App = () => {
  return <RestOfTheApp />;
};

export default AppRegistry.registerComponent("Your Amazing App", () =>
  Sentry.withTouchEventBoundary(App),
);

Each touch event is automatically logged as a breadcrumb and displays on the dashboard when an event occurs along with the component tree in which the touch event occurred. This component tree is logged using the name property of a component. By default, React Native will set this property automatically on components.

You can let Sentry know which components to track specifically by passing the sentry-label prop to them. If Sentry detects a component with a sentry-label within a touch's component tree, it will be logged on the dashboard as having occurred in that component.

For each component in the touch path, the SDK extracts a label and a name. The breadcrumb message uses the label if any component in the path has one; otherwise it falls back to the root component's name.

The label is determined by the first available value from:

  1. sentry-label prop
  2. Custom labelName prop (if configured on the boundary)
  3. accessibilityLabel prop
  4. aria-label prop
  5. testID prop
  6. Text content extracted from children (e.g. <Text>Save workout</Text>"Save workout")

The name comes from the Babel plugin annotation (data-sentry-component) or displayName. See Component Names for details.

This means apps that use accessibility labels, test IDs, or simply have text inside their touchable components get meaningful touch breadcrumbs automatically, without any extra configuration.

Copied
const YourCoolComponent = (props) => {
  return (
    <View sentry-label="CardContainer">
      <Text sentry-label="CoolText">You are cool</Text>
    </View>
  );
};

When Component Names are enabled (annotateReactComponents option), the Babel plugin automatically injects sentry-label props from static text content at build time. For example, a <Pressable> wrapping <Text>Save workout</Text> will automatically receive sentry-label="Save workout" during the build, without any manual annotation.

See Component Names — Automatic sentry-label Injection for configuration details.

When no label is found from props (steps 1–5 above), the SDK attempts to extract text from the touched component's children at runtime. This complements the build-time injection — it handles dynamic text, components not processed by the Babel plugin, or cases where annotateReactComponents is not enabled. For example, if you touch a button:

Copied
<Pressable>
  <Text>Add to cart</Text>
</Pressable>;

The breadcrumb label will automatically be "Add to cart" without needing any props.

Text extraction has the following limits:

  • Traverses up to 3 levels deep into the component tree
  • Visits up to 5 sibling nodes at each level
  • Truncates text at 64 characters

To disable runtime text extraction, set extractTextFromChildren to false (see Options).

To prevent masked content from leaking into breadcrumbs, the SDK respects Session Replay masking boundaries:

  • When maskAllText is enabled on mobileReplayIntegration (the default), sentry-label and text extraction from children are both skipped, since they may contain user-visible text content.
  • When the touched element is inside a Sentry.Mask boundary, sentry-label and text extraction are skipped for that element.
  • Developer-provided labels (custom labelName, accessibilityLabel, aria-label, testID) are never affected by masking.

To enable sentry-label and text extraction alongside Session Replay, set maskAllText: false:

Copied
Sentry.init({
  integrations: [Sentry.mobileReplayIntegration({ maskAllText: false })],
});

You can pass specific options to configure the boundary either as props to the Sentry.TouchEventBoundary component or as the second argument to the Sentry.withTouchEventBoundary higher-order component (HOC).

Copied
<Sentry.TouchEventBoundary
  ignoreNames={["BadComponent", /^Connect\(/, /^LibraryComponent$/]}
  labelName="testLabel"
>
  <RestOfTheApp />
</Sentry.TouchEventBoundary>;

breadcrumbCategory

String. The category assigned to the breadcrumb that is logged by the touch event.

breadcrumbType

String. The type assigned to the breadcrumb that is logged by the touch event.

maxComponentTreeSize

number, default: 20. The max number/depth of components to display when logging a touch's component tree.

ignoreNames

Array<string | RegExp>, Accepts strings and regular expressions. Component names to ignore when logging the touch event. This prevents unhelpful logs such as "Touch event within element: View" where you still can't tell which View it occurred in.

labelName

String. The name of a custom prop to look for when determining the label of a component. Takes priority over the automatic accessibilityLabel, aria-label, testID, and text extraction from children fallbacks.

extractTextFromChildren

boolean, default: true. Extract text content from children of touched components as a label fallback. Automatically disabled when Session Replay's maskAllText is enabled. Text inside Sentry.Mask boundaries is never extracted. Set to false to opt out entirely.

When bundling for production, React Native will minify class and function names to reduce the bundle size. This means that you won't get the full original component names in your touch event breadcrumbs and instead you will see minified names. Check out our troubleshooting guide for minified production bundles documentation to solve this.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").