From 05924558ed83e5fafe7e123dd3b50455098f6cd7 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Mon, 8 Jul 2024 18:57:25 +0200 Subject: [PATCH 1/5] Add React Component Tracking and Error Boundary to React Native docs pages --- .../integrations/component-monitoring.mdx | 77 +++++++ .../integrations/error-boundary.mdx | 194 ++++++++++++++++++ .../integrations/img/errorboundary-error.png | Bin 0 -> 358035 bytes .../react-native/integrations/redux.mdx | 1 + 4 files changed, 272 insertions(+) create mode 100644 docs/platforms/react-native/integrations/component-monitoring.mdx create mode 100644 docs/platforms/react-native/integrations/error-boundary.mdx create mode 100644 docs/platforms/react-native/integrations/img/errorboundary-error.png diff --git a/docs/platforms/react-native/integrations/component-monitoring.mdx b/docs/platforms/react-native/integrations/component-monitoring.mdx new file mode 100644 index 0000000000000..97ddeed069281 --- /dev/null +++ b/docs/platforms/react-native/integrations/component-monitoring.mdx @@ -0,0 +1,77 @@ +--- +title: Component Tracking +description: "Learn how Sentry's React Native SDK allows you to monitor the your application components lifecycle." +sidebar_order: 55 +--- + +Sentry's React Native SDK offers a feature to monitor the performance of your React components: component tracking. The SDK exports a `withProfiler` higher-order component that attaches React related spans to the current active span on the scope. This allows you to get a drilled-down view into how your components are behaving so you can do things like identify slow mounts or frequent updates, which might have an impact on your app's performance. + +## Prerequisites + +- To set up component tracking, you need to configure tracing. For details on how to do this, check out our [Tracing documentation](/platforms/react-native/tracing/). + +## Add `withProfiler` + +In the example below, the `withProfiler` higher-order component is used to instrument an app component. + +```javascript +import React from "react"; +import * as Sentry from "@sentry/react-native"; + +class App extends React.Component { + render() { + return ( + + + + + ); + } +} + +export default Sentry.withProfiler(App); +``` + +The React Profiler currently generates spans with three different kinds of op-codes: `ui.react.mount`, `ui.react.render`, and `ui.react.update`. + +`ui.react.mount` + +The span that represents how long it took for the profiled component to mount. + +`ui.react.render` + +The span that represents how long the profiled component was on a page. This span is only generated if the profiled component mounts and unmounts while a transaction is occurring. + +`ui.react.update` + +The span that represents when the profiled component updated. This span is only generated if the profiled component has mounted. + + + +In [React Strict Mode](https://react.dev/reference/react/StrictMode), certain component methods will be [invoked twice](https://react.dev/reference/react/StrictMode#fixing-bugs-found-by-double-rendering-in-development). This may lead to duplicate `ui.react.mount` spans. React Strict Mode only runs in development mode, so this will have no impact on your production traces. + + + +### Profiler Options + +The `withProfiler` higher-order component has a variety of options for further customization. They can be passed in as the second argument to the `withProfiler` function. + +```javascript +export default Sentry.withProfiler(App, { name: "CustomAppName" }); +``` + +`name` (string) + +The name of the component being profiled. By default, the name is taken from the component `displayName` property or the component `name` property. + +`includeRender` (boolean) + +If a `ui.react.render` span should be created by the Profiler. Set as true by default. + +`includeUpdates` (boolean) + +If `react.update` spans should be created by the Profiler. Set as true by default. We recommend setting this prop as false for components that will experience many rerenders, such as text input components, as the resulting spans can be very noisy. + +## Next Steps: + +- To track time to initial display and time to full display of your React Native application, check out also our [Time to Display guide](/platforms/react-native/tracing/instrumentation/time-to-display/). diff --git a/docs/platforms/react-native/integrations/error-boundary.mdx b/docs/platforms/react-native/integrations/error-boundary.mdx new file mode 100644 index 0000000000000..4c93ae95d7d25 --- /dev/null +++ b/docs/platforms/react-native/integrations/error-boundary.mdx @@ -0,0 +1,194 @@ +--- +title: React Error Boundary +excerpt: "" +description: "Learn how the React Native SDK exports an error boundary component that leverages React component APIs." +sidebar_order: 60 +--- + +The React Native SDK exports an error boundary component that leverages [React component APIs](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) to automatically catch and send JavaScript errors from inside a React component tree to Sentry. + +## Prerequisites + +- To use the Error Boundary component, you need to have the React Native SDK [installed and configured for error monitoring](/platforms/react-native/). + +## Use `Sentry.ErrorBoundary` + +```javascript +import React from "react"; +import * as Sentry from "@sentry/react"; + +An error has occurred

}> + +
; +``` + +The Sentry Error Boundary is also available as a higher order component. + +```javascript +import React from "react"; +import * as Sentry from "@sentry/react"; + +Sentry.withErrorBoundary(Example, { fallback:

an error has occurred

}); +``` + + + +In development mode, React will rethrow errors caught within an error boundary to the global error handler. This will result in Sentry only reporting an error from the global error handler, but not from the error boundary itself. We recommend testing the error boundary with a production build of React. + + + +In the example below, when the `` component hits an error, the `` component will send data about that error and the component tree to Sentry, open a user feedback dialog, and render a fallback UI. + +```javascript +import React from "react"; +import * as Sentry from "@sentry/react"; + +import { Example } from "../example"; + +function FallbackComponent() { + return
An error has occurred
; +} + +const myFallback = ; +// Alternatively: +// const myFallback = () => ; + +class App extends React.Component { + render() { + return ( + + + + ); + } +} + +export default App; +``` + + + +By default React [logs all errors to the console](https://github.com/facebook/react/blob/493f72b0a7111b601c16b8ad8bc2649d82c184a0/packages/react-reconciler/src/ReactFiberErrorLogger.js#L85), even if you are using a React error boundary. If you are using the `CaptureConsole` integration this means that Sentry will capture the error through the `CaptureConsole` integration and not through the error boundary. + + + +## Linked Errors + +In [React v17 and above](https://reactjs.org/blog/2020/08/10/react-v17-rc.html#native-component-stacks), the SDK will automatically parse the [error boundary](https://react.dev/reference/react/Component#componentdidcatch-parameters) `componentStack` and attach the full stacktrace to the event via `error.cause`. This requires the `nativeLinkedErrorsIntegration` to be enabled (enabled by default). To get the full source context, we recommend setting up [source maps](/platforms/react-native/sourcemaps/) for your project. + +![React Error Boundary stacktrace](./img/errorboundary-error.png) + +## Options + +The ErrorBoundary component exposes a variety of props that can be passed in for extra configuration. There are no required options, but we highly recommend that you set a fallback component. + +`fallback` (React.ReactNode or Function) + +A React element to render when the error boundary catches an error. Can be an actual React element (i.e. ``), or a function that returns a React element. If you provide a function, Sentry will call it with additional info and helpers (see example below). + +`onError` (Function) + +A function that gets called when the Error Boundary encounters an error. `onError` is useful if you want to propagate the error into a state management library like Redux, or if you want to check any side effects that could have occurred due to the error. + +`onMount` (Function) + +A function that gets called on ErrorBoundary `componentDidMount()`. + +`onUnmount` (Function) + +A function that gets called on ErrorBoundary `componentWillUnmount()`. + +`beforeCapture` (Function) + +A function that gets called before an error is sent to Sentry, allowing for extra tags or context to be added to the error. + +## Examples + +#### Setting a Fallback Function (Render Props) + +Below is an example where a fallback prop, using the [render props approach](https://react.dev/reference/react/cloneElement#passing-data-with-a-render-prop), is used to display a fallback UI on error. The fallback UI returns to a standard component state when reset using the `resetError()` API provided by the component through render props. + +```javascript +import React from "react"; +import { Button, Text } from "react-native" +import * as Sentry from "@sentry/react-native"; + +class MyComponent extends React.Component { + constructor(props) { + super(props); + this.state = { + message: "This is my app", + }; + } + + render() { + return ( + ( + + You have encountered an error + {error.toString()} + {componentStack} +