Sentry remote bug monitoring in frontend React apps

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 (). :



  1. build docs .



  2. GitHub Pages ( GitHub), docs master



  3. 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.



P.S. Sentry https://t.me/sentry_ru




All Articles