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
Post a Comment