We are exploring the use of Sentry with React.

This article is part of a series that starts with Sentry error reporting example: .
Implementing React
First, we need to add a new Sentry project for this application from the Sentry website. In this case, we choose React.
We will again implement our two buttons, Hello and Error, in a React application. We start by creating our starter application:
npx create-react-app react-appThen we import the Sentry package:
yarn add @sentry/browserand initialize it:
react-app / src / index.js
...
import * as Sentry from '@sentry/browser';
const RELEASE = '0.1.0';
if (process.env.NODE_ENV === 'production') {
Sentry.init({
dsn: 'https://303c04eac89844b5bfc908ceffc6757c@sentry.io/1289887',
release: RELEASE,
});
}
...Observations:
- During development, we have other mechanisms for monitoring issues, such as the console, so we enable Sentry only for production builds.
Next, we will implement our Hello and Error buttons and add them to the application:
react-app / src / Hello.js
import React, { Component } from 'react';
import * as Sentry from '@sentry/browser';
export default class Hello extends Component {
state = {
text: '',
};
render() {
const { text } = this.state;
return (
<div>
<button
onclick="{this.handleClick}"
>
Hello
</button>
<div>{text}</div>
</div>
)
}
handleClick = () => {
this.setState({
text: 'Hello World',
});
try {
throw new Error('Caught');
} catch (err) {
if (process.env.NODE_ENV !== 'production') {
return;
}
Sentry.captureException(err);
}
}
}react-app / src / MyError.js
import React, { Component } from 'react';
export default class MyError extends Component {
render() {
return (
<div>
<button
onclick="{this.handleClick}"
>
Error
</button>
</div>
)
}
handleClick = () => {
throw new Error('Uncaught');
}
}react-app / src / App.js
...import Hello from './Hello';
import MyError from './MyError';
class App extends Component {
render() {
return (
<div classname="App">
...
<hello />
<myerror />
</div>
);
}
}
export default App;Problem (Source Maps)
We can test Sentry with a production build by entering:
yarn buildand from the build folder enter:
npx http-server -c-1The problem we will immediately encounter is that Sentry error logs refer to line numbers in the minified package; not very helpful.

The Sentry service explains this by pulling source maps for the minified package after receiving the error. In this case, we run from localhost (unavailable to the Sentry service).
Solutions (Source Maps)
The solution to this problem comes down to running the application from a public web server. One straightforward way to do this is to use the GitHub Pages service (free). The steps to use it are usually as follows:
Copy the contents of the folder build in the folder docs to the root directory of the repository.
Enable GitHub Pages in the repository (from GitHub) to use the docs folder in master the branch
Push changes to GitHub
Note: after I realized that I needed to use create-react-app homepage function to serve the application. This amounted to adding the following to package.json:
"homepage": "https://larkintuckerllc.github.io/hello-sentry/"The final version of the deployed application is available at:
Illustration of Caught Errors
Let's go through pressing the Hello button.

With the error showing up as follows:

Observations:
- This error report cannot be clearer. BRAVO.
Illustration of Uncaught Errors
Similarly, let's go through pressing the button. Error.

With the error showing up as follows:

Best Handling of Uncaught Errors (Rendering)
Introduction to Error Boundaries
A JavaScript error in the UI should not crash the whole application. To address this for React users, React 16 introduces the concept of "error boundaries."
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the crashed component tree. They catch errors during rendering, in lifecycle methods, and in constructors of the components below them.
…
New Behavior for Uncaught Errors
This change is significant. From React 16 onwards, errors that aren't caught by any error boundary will unmount the entire React component tree.
— Dan Abramov —
An important clarification that took me some time to understand is that the aforementioned behavior only works for errors generated in render methods (or more likely, any of the lifecycle methods). For example, using error boundaries would be of no help with our button Error; that error occurred in the click handler.
Let’s create an example rendering error and then use error boundaries for a more graceful error handling.
react-app / src / MyRenderError
import React, { Component } from 'react';
export default class MyRenderError extends Component {
state = {
flag: false,
};
render() {
const { flag } = this.state;
return (
<div>
<button
onclick="{this.handleClick}"
>
Render Error
</button>
{ flag && <div>{flag.busted.bogus}</div> }
</div>
)
}
handleClick = () => {
this.setState({
flag: true,
});
}
}Observation:
When the button is clicked, React Starting with Chrome 77, information about the use of EV certificates will only appear in the dropdown menu shown when clicking on the secure connection icon. In 2018, a similar decision was made by Apple for the Safari browser, implemented in releases of iOS 12 and macOS 10.14. It’s worth noting that EV certificates confirm the stated identification parameters and require the certificate authority to verify domain ownership documents and physical presence of the resource owner. flag.busted.bogus, which generates an error
Without an error boundary, the entire component tree will unmount.
Then we write our error boundary code (utilizes the new lifecycle method componentDidCatch); this is essentially the example provided in Dan Abramov's article:
react-app / src / ErrorBoundary.js
import React, { Component } from 'react';
import * as Sentry from '@sentry/browser';
export default class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(err, info) {
this.setState({ hasError: true });
Sentry.captureException(err);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}Finally, we use this component:
react-app / src / App.js
...import MyRenderError from './MyRenderError';
class App extends Component {
render() {
return (
<errorboundary>
<div classname="App">
...
</div>
</errorboundary>
);
}
}
...With this, pressing the Render Error button displays the fallback UI and reports the error to Sentry.


Completion
I hope you found this useful.
P.S.
P.S. Telegram chat about Sentry
Source: habr.com
