We are looking into using Sentry with React.
This article is part of a series starting with Sentry Error Reporting by Example: Part 1 .
React implementation
First we need to add a new Sentry project for this application; from the Sentry website. In this case, we choose React.
We will reimplement our two buttons, Hello and Error, in a React application. We start by creating our starter application:
npx create-react-app react-app
Then we import the Sentry package:
yarn add @sentry/browser
and 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 to monitor issues, such as the console, so we only enable Sentry for production builds
We then 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 the Sentry with a production build by entering:
yarn build
and from the build folder enter:
npx http-server -c-1
The problem we will immediately encounter is that the Sentry error entries refer to line numbers in the reduced package; not very helpful.
Sentry , . localhost ( Sentry).
( )
-. , GitHub Pages (). :
build docs .
GitHub Pages ( GitHub), docs master
GitHub
: , , create-create-app . package.json:
"homepage": "https://larkintuckerllc.github.io/hello-sentry/"
:
https://larkintuckerllc.github.io/hello-sentry/
Hello.
, :
:
- , BRAVO.
, Error.
, :
()
JavaScript . React, React 16 " ".
β React, JavaScript , , . , .
β¦
. React 16, , - , React.
β Dan Abramov β Error Handling in React 16
, , , , , (, , ). , Error; .
, .
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,
});
}
}
:
, React flag.busted.bogus,
( componentDidCatch); , , , :
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;
}
}
, :
react-app / src / App.js
...
import MyRenderError from './MyRenderError';
class App extends Component {
render() {
return (
<ErrorBoundary>
<div className="App">
...
</div>
</ErrorBoundary>
);
}
}
...
Render Error Sentry.
, .
P.S. Sentry https://t.me/sentry_ru