/** * External dependencies */ import { Component, ReactNode, ErrorInfo } from 'react'; import { __ } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; import { captureException } from '@woocommerce/remote-logging'; import { bumpStat } from '@woocommerce/tracks'; /** * Internal dependencies */ import './style.scss'; type ErrorBoundaryProps = { children: ReactNode; }; type ErrorBoundaryState = { hasError: boolean; error: Error | null; errorInfo: ErrorInfo | null; }; export class ErrorBoundary extends Component< ErrorBoundaryProps, ErrorBoundaryState > { constructor( props: ErrorBoundaryProps ) { super( props ); this.state = { hasError: false, error: null, errorInfo: null }; } static getDerivedStateFromError( error: Error ): Partial< ErrorBoundaryState > { return { hasError: true, error }; } componentDidCatch( error: Error, errorInfo: ErrorInfo ) { this.setState( { errorInfo } ); bumpStat( 'error', 'unhandled-js-error-during-render' ); // Limit the component stack to 10 calls so we don't send too much data. const componentStack = errorInfo.componentStack .trim() .split( '\n' ) .slice( 0, 10 ) .map( ( line ) => line.trim() ); captureException( error, { severity: 'critical', extra: { componentStack, }, } ); } handleRefresh = () => { window.location.reload(); }; handleOpenSupport = () => { window.open( 'https://wordpress.org/support/plugin/woocommerce/', '_blank' ); }; render() { if ( this.state.hasError ) { return (

{ __( 'Oops, something went wrong', 'woocommerce' ) }

{ __( 'We’re sorry for the inconvenience. Please try reloading the page, or you can get support from the community forums.', 'woocommerce' ) }

{ __( 'Click for error details', 'woocommerce' ) }
{ this.state.error && this.state.error.toString() }

{ this.state.errorInfo && this.state.errorInfo.componentStack }

); } return this.props.children; } }