React Error Boundary

With a fallback with https://ant.design components

import {
    Component,
    type ErrorInfo,
    type ReactNode,
    useState,
} from "react";

import { Alert, Button, Collapse, Space, Typography } from "antd";

const { Text, Paragraph } = Typography;

interface ErrorBoundaryProps {
    children: ReactNode;
}

interface ErrorBoundaryState {
    hasError: boolean;
    error: Error | null;
    errorInfo: ErrorInfo | null;
}

interface ErrorBoundaryFallbackProps {
    error: Error | null;
    errorInfo: ErrorInfo | null;
}

function ErrorBoundaryFallback({
    error,
    errorInfo,
}: ErrorBoundaryFallbackProps) {
    const [showDetails, setShowDetails] = useState(false);

    const errorMessage =
        error?.message || "Er is een onbekende fout opgetreden.";

    const errorStack =
        error?.stack || "Geen stack trace beschikbaar.";

    const componentStack =
        errorInfo?.componentStack || "Geen component stack beschikbaar.";

    return (
        <div style={{ padding: 16 }}>
            <Alert
                title="Er is een fout opgetreden"
                showIcon
                description={errorMessage}
                type="error"
                action={
                    <Button
                        size="small"
                        danger
                        onClick={() => setShowDetails((value) => !value)}
                    >
                        {showDetails ? "Verberg details" : "Detail"}
                    </Button>
                }
            />

            {showDetails && (
                <Collapse
                    style={{ marginTop: 16 }}
                    items={[
                        {
                            key: "error",
                            label: "Error details",
                            children: (
                                <Space
                                    size="middle"
                                    style={{ width: "100%" }}
                                >
                                    <div>
                                        <Text strong>Message</Text>
                                        <Paragraph
                                            copyable
                                            style={{ marginBottom: 0 }}
                                        >
                                            {errorMessage}
                                        </Paragraph>
                                    </div>

                                    <div>
                                        <Text strong>Stack trace</Text>
                                        <Paragraph
                                            copyable
                                            style={{
                                                whiteSpace: "pre-wrap",
                                                marginBottom: 0,
                                            }}
                                        >
                                            {errorStack}
                                        </Paragraph>
                                    </div>

                                    <div>
                                        <Text strong>Component stack</Text>
                                        <Paragraph
                                            copyable
                                            style={{
                                                whiteSpace: "pre-wrap",
                                                marginBottom: 0,
                                            }}
                                        >
                                            {componentStack}
                                        </Paragraph>
                                    </div>
                                </Space>
                            ),
                        },
                    ]}
                />
            )}
        </div>
    );
}

class ErrorBoundaryClass extends Component<
    ErrorBoundaryProps,
    ErrorBoundaryState
> {
    state: ErrorBoundaryState = {
        hasError: false,
        error: null,
        errorInfo: null,
    };

    static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {
        return {
            hasError: true,
            error,
        };
    }

    componentDidCatch(error: Error, errorInfo: ErrorInfo) {
        console.error("ErrorBoundary:", error);
        console.error("ErrorInfo:", errorInfo);

        this.setState({
            error,
            errorInfo,
        });
    }

    render() {
        if (this.state.hasError) {
            return (
                <ErrorBoundaryFallback
                    error={this.state.error}
                    errorInfo={this.state.errorInfo}
                />
            );
        }

        return this.props.children;
    }
}

/**
 * Functionele wrapper zodat je deze component
 * gewoon als JSX component kunt gebruiken.
 */
export function ErrorBoundary({
    children,
}: ErrorBoundaryProps) {
    return (
        <ErrorBoundaryClass>
            {children}
        </ErrorBoundaryClass>
    );
}

export default ErrorBoundary;
102450cookie-checkReact Error Boundary