Return

All tests / src/components/ErrorBoundary index.tsx

100% Statements 16/16
100% Branches 1/1
100% Functions 4/4
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 751x 1x 1x 1x 1x 1x 1x 1x       6x 5x           4x                         2x       9x                                                                   5x       3x  
import React from 'react';
import Link from 'next/link';
import { FormattedMessage } from 'react-intl';
import ControlButtons from '@/components/ControlButtons';
import SEO from '@/components/SEO';
import Dialog from '@/components/Dialog';
import Layout from '@/components/Layout';
import styles from '../../pages/error.module.css';
 
class ErrorBoundary extends React.Component<React.PropsWithChildren<unknown>, { hasError: boolean; error?: Error }> {
    constructor(props: React.PropsWithChildren<unknown>) {
        super(props);
        this.state = {
            hasError: false,
        };
    }
 
    static getDerivedStateFromError(error: Error) {
        return { hasError: true, error };
    }
 
    /**
     * SDD-L08. The boundary used to render `this.state.error?.message` straight to the visitor.
     *
     * That is a React error object from a production bundle: at best it reads "Minified React error
     * #418", at worst it carries a fragment of internal state, a URL, or a property name from
     * whatever threw. It tells a reader nothing they can act on and tells anyone else more than they
     * should see. The detail belongs in the console, where a developer can read it; the page gets a
     * sentence in the visitor's own language.
     */
    componentDidCatch(error: Error, info: React.ErrorInfo) {
        console.error('Unhandled render error:', error, info.componentStack);
    }
 
    render() {
        if (this.state.hasError) {
            return (
                <Layout>
                    <>
                        <SEO
                            meta={{
                                title: 'Error',
                                description: '',
                                noindex: true,
                            }}
                        />
                        <Dialog
                            open
                            modalMode
                            withPadding
                            header={<ControlButtons disabled />}
                            body={
                                // A class component cannot call useIntl. FormattedMessage reads the
                                // same context, and _app mounts IntlProvider outside this boundary.
                                <div className={styles.body}>
                                    <p>
                                        <FormattedMessage id="error.boundary.message" />
                                    </p>
                                    <Link href="/" className={styles.home}>
                                        <FormattedMessage id="error.home" />
                                    </Link>
                                </div>
                            }
                        />
                    </>
                </Layout>
            );
        }
 
        return this.props.children;
    }
}
 
export default ErrorBoundary;