Can You Catch All Errors Of A React.js App With A Try/catch Block?


Answer :

React 16 introduced Error Boundaries and the componentDidCatch lifecycle method:

class ErrorBoundary extends React.Component {   constructor(props) {     super(props);     this.state = { hasError: false };   }    componentDidCatch(error, info) {     // Display fallback UI     this.setState({ hasError: true });     // You can also log the error to an error reporting service     logErrorToMyService(error, info);   }    render() {     if (this.state.hasError) {       // You can render any custom fallback UI       return <h1>Something went wrong.</h1>;     }     return this.props.children;   } } 

Then you can use it as a regular component:

<ErrorBoundary>   <MyWidget /> </ErrorBoundary> 

Or you can wrap your root component with the npm package react-error-boundary, and set a fallback component and behavior.

import {ErrorBoundary} from 'react-error-boundary';  const myErrorHandler = (error: Error, componentStack: string) => {   // ... };  <ErrorBoundary onError={myErrorHandler}>   <ComponentThatMayError /> </ErrorBoundary> 

this is what I ended up using

EDIT: React 16 introduced proper ways to do this, see @goldylucks answer.

componentWillMount: function () {     this.startErrorLog(); } startErrorLog:function() {     window.onerror = (message,file,line,column,errorObject) =>     {         column = column || (window.event && window.event.errorCharacter);         var stack = errorObject ? errorObject.stack : null;          //trying to get stack from IE         if(!stack)         {             var stack = [];             var f = arguments.callee.caller;             while (f)             {                 stack.push(f.name);                 f = f.caller;             }             errorObject['stack'] = stack;         }          var data = {             message:message,             file:file,             line:line,             column:column,             errorStack:stack,         };          //here I make a call to the server to log the error          //the error can still be triggered as usual, we just wanted to know what's happening on the client side         return false;     } } 

You can leverage React's BatchingStrategy API to easily wrap a try/catch around all of your React code. The benefit of this over window.onerror is that you get a nice stack trace in all browsers. Even modern browsers like Microsoft Edge and Safari don't provide stack traces to window.onerror.

Here's what it looks like with React 15.4:

import ReactUpdates from "react-dom/lib/ReactUpdates"; import ReactDefaultBatchingStrategy from "react-dom/lib/ReactDefaultBatchingStrategy";  let isHandlingError = false; const ReactTryCatchBatchingStrategy = {   // this is part of the BatchingStrategy API. simply pass along   // what the default batching strategy would do.   get isBatchingUpdates () { return ReactDefaultBatchingStrategy.isBatchingUpdates; },    batchedUpdates (...args) {     try {       ReactDefaultBatchingStrategy.batchedUpdates(...args);     } catch (e) {       if (isHandlingError) {         // our error handling code threw an error. just throw now         throw e;       }        isHandlingError = true;       try {         // dispatch redux action notifying the app that an error occurred.         // replace this with whatever error handling logic you like.         store.dispatch(appTriggeredError(e));       } finally {         isHandlingError = false;       }     }   }, };  ReactUpdates.injection.injectBatchingStrategy(ReactTryCatchBatchingStrategy); 

Full writeup here: https://engineering.classdojo.com/blog/2016/12/10/catching-react-errors/


Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?