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 | import { Component, type ErrorInfo, type ReactNode } from "react"; import { logger } from "../logger"; interface Props { /** Rendered when the child throws during load. */ fallback: ReactNode; /** Short label for logs (e.g. "zone:office", "character:mayor"). */ label: string; children: ReactNode; } interface State { failed: boolean; } /** * Small error boundary for GLB-loading subtrees. @react-three/drei's * `useGLTF` throws (or rejects the Suspense promise) on a permanent load * failure; without a boundary that blows up the whole <Canvas>. This * catches the error, logs it once, and renders the provided Tier 1 cube * fallback so the scene keeps rendering. */ export class GltfErrorBoundary extends Component<Props, State> { state: State = { failed: false }; static getDerivedStateFromError(): State { return { failed: true }; } componentDidCatch(error: Error, info: ErrorInfo): void { logger.warn("GLB load failed, falling back to cube", { label: this.props.label, error: error.message, componentStack: info.componentStack }); } render(): ReactNode { if (this.state.failed) return this.props.fallback; return this.props.children; } } |