生产就绪的 React 错误边界:优雅失败的模式
发布: (2026年4月7日 GMT+8 16:52)
4 分钟阅读
原文: Dev.to
Source: Dev.to
未处理的渲染错误会导致整个 React 树崩溃。错误边界可以限制损害。以下是在生产环境中有效使用它们的方法。
问题
// If UserCard throws, the entire page goes blank
function Dashboard() {
return (
<>
{/* if this throws, everything dies */}
</>
)
}基本错误边界
import React, { Component, ReactNode } from 'react'
interface Props {
children: ReactNode
fallback?: ReactNode
}
interface State {
hasError: boolean
error: Error | null
}
class ErrorBoundary extends Component<Props, State> {
state: State = { hasError: false, error: null }
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error }
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
console.error('ErrorBoundary caught:', error, info.componentStack)
}
render() {
if (this.state.hasError) {
return this.props.fallback ?? <>Something went wrong</>
}
return this.props.children
}
}使用 react-error-boundary
不要自己实现——使用经过实战检验的库:
npm install react-error-boundaryimport { ErrorBoundary, FallbackProps } from 'react-error-boundary'
function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
return (
<>
<h2>Something went wrong</h2>
<p>{error.message}</p>
<button onClick={resetErrorBoundary}>Try again</button>
</>
)
}
function Dashboard() {
return (
<ErrorBoundary FallbackComponent={ErrorFallback}>
{/* Your dashboard content */}
</ErrorBoundary>
)
}粒度边界
将独立的部分进行包装——其中一个部分的失败不应影响其他部分:
function Dashboard() {
return (
<>
<ErrorBoundary FallbackComponent={WidgetError}>
{/* Widget A */}
</ErrorBoundary>
<ErrorBoundary FallbackComponent={WidgetError}>
{/* Widget B */}
</ErrorBoundary>
<ErrorBoundary FallbackComponent={WidgetError}>
{/* Widget C */}
</ErrorBoundary>
</>
)
}
function WidgetError({ error, resetErrorBoundary }: FallbackProps) {
return (
<>
<p>Failed to load widget</p>
<button onClick={resetErrorBoundary}>Retry</button>
</>
)
}将错误记录到您的错误监控服务
import * as Sentry from '@sentry/nextjs'
function onError(error: Error, info: { componentStack: string }) {
Sentry.captureException(error, {
extra: { componentStack: info.componentStack },
})
}路由更改时重置
import { useLocation } from 'react-router-dom'
import { ErrorBoundary } from 'react-error-boundary'
function App() {
const location = useLocation()
return (
<ErrorBoundary
onReset={() => {
// Reset logic when the route changes
}}
resetKeys={[location.pathname]}
>
{/* Your app routes */}
</ErrorBoundary>
)
}什么错误边界 不会 捕获
- 事件处理函数中的错误(在处理函数内部使用
try/catch) - 异步代码中的错误(使用
try/catch并结合组件状态处理) - 服务端渲染期间的错误
- 在边界组件本身内部抛出的错误
// This WON’T be caught by an error boundary:
function Button() {
const handleClick = async () => {
try {
await submitForm() // async error — handle here
} catch (err) {
setError(err.message)
}
}
return <button onClick={handleClick}>Submit</button>
}路由级别边界(Route‑Level Boundaries)在 Next.js 中
在 Next.js App Router 中,使用 error.tsx:
// app/dashboard/error.tsx
'use client'
export default function DashboardError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<>
<h2>Dashboard failed to load</h2>
<button onClick={reset}>Try again</button>
</>
)
}此文件充当整个 /dashboard 路由段的内置错误边界。
生产检查清单
- Next.js 中的路由级
error.tsx文件 - 对独立小部件进行细粒度边界划分
- 错误报告已接入(Sentry / LogRocket)
- 有意义的回退 UI(不仅仅是白屏)
- 重置按钮,让用户能够恢复
- 事件处理程序中的异步错误处理
AI SaaS Starter Kit 已集成 Sentry,配置了路由级错误边界,并预先接入所有生产环境错误处理模式。一次性 $99 — 克隆后即可发布。