I've made a react application which is not running live, and the people that use it note that very occasionally some strange error occurs. I don't know why or what happens, and can't reproduce it.
So I'm wondering if there is a way to wrap the entire app, or parts of it, in a try/catch block so that I can send the errors to an error log on the server?
All I've read so far is that you could wrap the entire render function in a try/catch, but that would not catch any errors due to user interation right?
Error boundaries were introduced in React 16 as a way to catch and handle JavaScript errors that occur in the UI parts of our component. So error boundaries only catch errors that occur in a lifecycle method, render method, and inside Hooks like useEffect .
catch statement can be used to catch JavaScript errors in React components. This is because the try... catch statement only works for imperative code, as opposed to the declarative code we have in components. This error fallback UI has been clipped to show the relevant part.
As is documented, try/catch blocks can't handle StackOverflowException and OutOfMemoryException.
The “try… First, the code in try {...} is executed. If there were no errors, then catch (err) is ignored: the execution reaches the end of try and goes on, skipping catch . If an error occurs, then the try execution is stopped, and control flows to the beginning of catch (err) .
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() { this.startErrorLog(); } startErrorLog() { 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; }; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With