Source: ErrorBoundary.jsx

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { WarningOutlined } from '@ant-design/icons';
import { getMsg } from './locale';

export const getGenericMsg = () => getMsg('error.generic');

const ErrorTag = styled('h2')`
    color: red;
`;
const DefaultError = () => (
    <ErrorTag>
        <WarningOutlined /> {getGenericMsg()}
    </ErrorTag>);
/**
 * Usage:
 * 1) Wrap components to "try/catch" with:
 *
 *     import { ErrorBoundary } from 'oskari-ui/util';
 *     <ErrorBoundary> .. the usual JSX ... </ErrorBoundary>
 *
 * 2) (optional) Create custom error handler to show when error happens on wrapped components:
 *
 *      export const CustomError = ({info}) => {
 *          console.log(info);
 *          return (<b>BOOM!</b>);
 *      };
 *
 * 3) (optional) Pass custom error element for customizing the error display:
 *
 *     import {CustomError} from './CustomError';
 *     <ErrorBoundary errorComponent={CustomError}>
 *
 * 4) See more:
 * - https://reactjs.org/docs/error-boundaries.html
 */
export class ErrorBoundary extends React.Component {
    constructor(props) {
        super(props);
        this.errorComp = props.errorComponent;
        this.hideError = !!props.hide;
        this.debugInfo = props.debug;
        this.state = { hasError: false };
    }

    componentDidCatch (error, errorInfo) {
        const log = Oskari.log('React/ErrorBoundary');
        log.error(error);
        if (this.debugInfo) {
            log.info('Debug info', this.debugInfo);
        }
        this.setState({
            hasError: true,
            errorInfo });
    }

    render () {
        if (this.state.hasError) {
            if (this.hideError) {
                return null;
            }
            const ErrorComp = this.errorComp || DefaultError;
            return (<ErrorComp info={this.state.errorInfo}/>);
        }
        return this.props.children;
    }
}
ErrorBoundary.propTypes = {
    // boolean to just skip without showing an error
    hide: PropTypes.bool,
    // info to include in logging if an error occurs
    debug: PropTypes.object,
    // custom component for rendering an error message
    errorComponent: PropTypes.elementType,
    // children are rendered when there is no error
    children: PropTypes.node
};