Get started with React

Getting Opbeat set up to get detailed insights about performance from real users and log exceptions in React applications is easy.

opbeat-react will automatically measure route changes and user interactions in your application and instrument components, AJAX calls, Redux dispatches etc. to give you detailed insights into what kind of experience your users are having. opbeat-react will also automatically log exceptions to Opbeat.

Note: Opbeat React is currently in BETA.

Installation

Create a new app in your Opbeat organization and select “React”.

Download from npm

Install the module from npm. The package is called opbeat-react.

Run the following command in your project directory:

$ npm install --save opbeat-react babel-plugin-add-react-displayname

This also installs our babel plugin. The plugin will automatically set MyComponent.displayName = 'MyComponent' to ensure that component names survive the minification/uglification process.

Configuration

To enable Opbeat, you need to import the library and then call initOpbeat with some tokens. These tokens are available in the Opbeat web interface.

Make sure to import opbeat-react before anything else in your application.

import initOpbeat from 'opbeat-react'

initOpbeat({
  orgId: '470e8f31bc7b4f4395143091fe752e8c',
  appId: '9aac8591cc',
});

If you use React Router v2.x or v3.x, import ‘opbeat-react/router’

import initOpbeat from 'opbeat-react'
// enable react-router instrumentation
import 'opbeat-react/router'

initOpbeat({
  orgId: '470e8f31bc7b4f4395143091fe752e8c',
  appId: '9aac8591cc',
});

If you’re using Redux, add the Opbeat middleware as the last middleware in your chain:

// enable redux instrumentation using the middleware
// NOTE: make sure you put the opbeat middleware last!
import { createOpbeatMiddleware } from 'opbeat-react/redux'

const store = createStore(
  reducer,
  applyMiddleware(
    thunk,
    createOpbeatMiddleware(),  // make sure this is the last one
  ),
);

Finally, remember to add the plugin to your .babelrc or your webpack configuration:

.babelrc:

{
  "presets": [....],
  "plugins": [
    ["add-react-displayname"]
  ]
}

webpack.conf:

Look for the query key:

query: {
  presets: [....],
  plugins: ["add-react-displayname"]
}

Staging and local environments

You should create separate apps on Opbeat for production, staging and local environments. You’ll get separate tokens for each app on Opbeat. You can then do something like:

import initOpbeat from 'opbeat-react'
import 'opbeat-react/router' // enable react-router instrumentation

if (process.env.NODE_ENV === 'production') {
  initOpbeat({
    orgId: '470e8f31bc7b4f4395143091fe752e8c',
    appId: '9aac8591cc', // production app id
  });
}else if(process.env.NODE_ENV === 'staging') {
  initOpbeat({
    orgId: '470e8f31bc7b4f4395143091fe752e8c',
    appId: '9aac8591cc', // staging app id
  });
}
// in local environments, don't call initOpbeat

This requires the webpack plugin DefinePlugin to be correctly set up to define process.env.

Set context information

It’s often useful to include additional information in performance data and exceptions logged to Opbeat. You can do this in the following manner:

import { setUserContext, setExtraContext } from 'opbeat-react'

class OfficeStatus extends React.Component {
  componentDidMount() {
    setUserContext({
      id: 19,
      email: 'ron@opbeat.com',
      username: 'roncohen',
    });

    setExtraContext({
      coffeeLevel: 'low',
      milkSolution: 'skim milk',
    });
  }
}

For projects with Redux, Opbeat will automatically include the content of the store as well as the type of the last 10 actions. This can be disabled by setting redux.actionsCount and redux.sendStateOnException to something falsy in the call to initOpbeat.

Manual error logging

If you happen to manually catch an error, you can send it up to Opbeat like so:

import { captureError } from 'opbeat-react'

try {
  throw new Error('Everything is broken')
} catch (err) {
  captureError(err)
}

Support

opbeat-react works with react-router 2.x and 3.x and react 0.14.x and 15.x

Opbeat will automatically determine if the browser is supported and disable itself if the browser is not supported.

IE9 and below is not supported. But in general, every modern browser is supported.

Setting up CORS

On browsers that support Cross-Origin Resource Sharing (CORS), Opbeat is able to collect much more detailed information about exceptions.

To enable CORS, first set up your server to return the right Access-Control-Allow-Origin headers. enable-cors.org has a comprehensive guide for different server software.

Then, add the crossorigin attribute to <script> tags (only do this to JavaScript you host yourself or have verified that the respective server returns the correct Access-Control-Allow-Origin headers). Here’s an example:

<script src="/static/js/scripts.js" crossorigin></script>

Note: make sure to force browser caches to invalidate.

Because browsers cache resources including the Access-Control-Allow-Origin header, you need to force these caches to invalidate. The right way to invalidate depends a bit on your setup, but the easiest one is to change the URLs of your scripts by appending a query string parameter, e.g.:

<script src="/static/js/scripts.js?v1" crossorigin></script>

Source Maps

We support source maps to reverse JavaScript minification. If your build script generates source maps, and includes the sourceMappingURL in the generated JavaScript, we will try to detect and download the source map.

Read more in the Source Maps for frontend JavaScript article.

Troubleshooting

Component names garbled

If component names are shown as single letters (e, t, f etc.) in the Opbeat interface, you might not have set up babel-plugin-add-react-displayname correctly. Make sure it’s installed and appears in your webpack or babelrc configuration. If you know which component is not appearing with its correct name, try settings .displayName manually on that component. For example, if Provider shows up as e (or similar):

import ReactDOM from 'react-dom'
import React from 'react'
import { Router, Route } from 'react-router'

import { Provider } from 'react-redux'
Provider.displayName = 'Provider';

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <Route path="/" component={App}>
      </Route>
    </Router>
  </Provider>,
  document.getElementById('mount')
);

Other problems

Please do not hesitate to get in contact with us at support@opbeat.com