// Forked from: https://www.npmjs.com/package/react-error-boundary import * as React from 'react'; const changedArray = (a: Array = [], b: Array = []) => a.length !== b.length || a.some((item, index) => !Object.is(item, b[index])); interface FallbackProps { error: Error; resetErrorBoundary: (...args: Array) => void; } interface ErrorBoundaryPropsWithComponent { onResetKeysChange?: (prevResetKeys: Array | undefined, resetKeys: Array | undefined) => void; onReset?: (...args: Array) => void; onError?: (error: Error, info: { componentStack: string }) => void; resetKeys?: Array; FallbackComponent: React.ComponentType; } declare function FallbackRender(props: FallbackProps): React.ReactElement | null; interface ErrorBoundaryPropsWithRender { onResetKeysChange?: (prevResetKeys: Array | undefined, resetKeys: Array | undefined) => void; onReset?: (...args: Array) => void; onError?: (error: Error, info: { componentStack: string }) => void; resetKeys?: Array; fallbackRender: typeof FallbackRender; } interface ErrorBoundaryPropsWithFallback { onResetKeysChange?: (prevResetKeys: Array | undefined, resetKeys: Array | undefined) => void; onReset?: (...args: Array) => void; onError?: (error: Error, info: { componentStack: string }) => void; resetKeys?: Array; fallback: React.ReactElement | null; } type ErrorBoundaryProps = ErrorBoundaryPropsWithFallback | ErrorBoundaryPropsWithComponent | ErrorBoundaryPropsWithRender; type ErrorBoundaryState = { error: Error | null }; const initialState: ErrorBoundaryState = { error: null }; class ErrorBoundary extends React.Component>, ErrorBoundaryState> { static getDerivedStateFromError(error: Error) { return { error }; } state = initialState; updatedWithError = false; resetErrorBoundary = (...args: Array) => { this.props.onReset?.(...args); this.reset(); }; reset() { this.updatedWithError = false; this.setState(initialState); } componentDidCatch(error: Error, info: React.ErrorInfo) { this.props.onError?.(error, info); } componentDidMount() { const { error } = this.state; if (error !== null) { this.updatedWithError = true; } } componentDidUpdate(prevProps: ErrorBoundaryProps) { const { error } = this.state; const { resetKeys } = this.props; // There's an edge case where if the thing that triggered the error // happens to *also* be in the resetKeys array, we'd end up resetting // the error boundary immediately. This would likely trigger a second // error to be thrown. // So we make sure that we don't check the resetKeys on the first call // of cDU after the error is set if (error !== null && !this.updatedWithError) { this.updatedWithError = true; return; } if (error !== null && changedArray(prevProps.resetKeys, resetKeys)) { this.props.onResetKeysChange?.(prevProps.resetKeys, resetKeys); this.reset(); } } render() { const { error } = this.state; // @ts-expect-error ts(2339) (at least one of these will be defined though, and we check for their existence) const { fallbackRender, FallbackComponent, fallback } = this.props; if (error !== null) { const props = { error, resetErrorBoundary: this.resetErrorBoundary, }; if (React.isValidElement(fallback)) { return fallback; } else if (typeof fallbackRender === 'function') { return (fallbackRender as typeof FallbackRender)(props); } else if (FallbackComponent) { return ; } else { throw new Error('ErrorBoundary requires either a fallback, fallbackRender, or FallbackComponent prop'); } } return this.props.children; } } function useErrorHandler

(givenError?: P | null | undefined): React.Dispatch> { const [error, setError] = React.useState

(null); if (givenError) throw givenError; if (error) throw error; return setError; } export { ErrorBoundary, useErrorHandler }; export type { FallbackProps, ErrorBoundaryPropsWithComponent, ErrorBoundaryPropsWithRender, ErrorBoundaryPropsWithFallback, ErrorBoundaryProps }; /* eslint @typescript-eslint/no-throw-literal: "off", @typescript-eslint/prefer-nullish-coalescing: "off" */