You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.1 KiB

import React from 'react';
import type { ReactNode } from 'react';
import { warning, error } from '../../dev-warning';
import { noop } from '../../empty';
import bindEvents from '../event-bindings/bind-events';
import { RbdInvariant } from '../../invariant';
import type { AppCallbacks } from './drag-drop-context-types';
interface Props {
children: (setCallbacks: (callbacks: AppCallbacks) => void) => ReactNode;
}
export default class ErrorBoundary extends React.Component<Props> {
callbacks: AppCallbacks | null = null;
unbind: () => void = noop;
componentDidMount() {
this.unbind = bindEvents(window, [
{
eventName: 'error',
fn: this.onWindowError,
},
]);
}
componentDidCatch(err: Error) {
if (err instanceof RbdInvariant) {
if (process.env.NODE_ENV !== 'production') {
error(err.message);
}
this.setState({});
return;
}
// throwing error for other error boundaries
// eslint-disable-next-line no-restricted-syntax
throw err;
}
componentWillUnmount() {
this.unbind();
}
onWindowError = (event: ErrorEvent) => {
const callbacks: AppCallbacks = this.getCallbacks();
if (callbacks.isDragging()) {
callbacks.tryAbort();
warning(`
An error was caught by our window 'error' event listener while a drag was occurring.
The active drag has been aborted.
`);
}
const err: Error | null = event.error;
if (err instanceof RbdInvariant) {
// Marking the event as dealt with.
// This will prevent any 'uncaught' error warnings in the console
event.preventDefault();
if (process.env.NODE_ENV !== 'production') {
error(err.message);
}
}
};
getCallbacks = (): AppCallbacks => {
if (!this.callbacks) {
// eslint-disable-next-line no-restricted-syntax
throw new Error('Unable to find AppCallbacks in <ErrorBoundary/>');
}
return this.callbacks;
};
setCallbacks = (callbacks: AppCallbacks) => {
this.callbacks = callbacks;
};
render() {
return this.props.children(this.setCallbacks);
}
}