45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { Component, Suspense, type ErrorInfo, type ReactNode } from "react";
|
|
|
|
type LazyContentProps = {
|
|
children: ReactNode;
|
|
pending: ReactNode;
|
|
failed: ReactNode;
|
|
};
|
|
|
|
type LazyLoadErrorBoundaryProps = {
|
|
children: ReactNode;
|
|
fallback: ReactNode;
|
|
};
|
|
|
|
type LazyLoadErrorBoundaryState = {
|
|
failed: boolean;
|
|
};
|
|
|
|
export function LazyContent({ children, pending, failed }: LazyContentProps) {
|
|
return (
|
|
<LazyLoadErrorBoundary fallback={failed}>
|
|
<Suspense fallback={pending}>{children}</Suspense>
|
|
</LazyLoadErrorBoundary>
|
|
);
|
|
}
|
|
|
|
class LazyLoadErrorBoundary extends Component<
|
|
LazyLoadErrorBoundaryProps,
|
|
LazyLoadErrorBoundaryState
|
|
> {
|
|
state: LazyLoadErrorBoundaryState = { failed: false };
|
|
|
|
static getDerivedStateFromError(): LazyLoadErrorBoundaryState {
|
|
return { failed: true };
|
|
}
|
|
|
|
componentDidCatch(_error: unknown, _errorInfo: ErrorInfo) {
|
|
// The local fallback keeps the rest of the navigation UI usable. A reload
|
|
// can then pick up a newer PWA chunk after a deployment.
|
|
}
|
|
|
|
render() {
|
|
return this.state.failed ? this.props.fallback : this.props.children;
|
|
}
|
|
}
|