error.js
errorファイルを使用することで、予期しないランタイムエラーを処理し、フォールバックUIを表示することができます。
'use client' // エラーバウンダリーはClient Componentsである必要があります
import { useEffect } from 'react'
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
useEffect(() => {
// エラーをエラーレポートサービスにログします
console.error(error)
}, [error])
return (
<div>
<h2>Something went wrong!</h2>
<button
onClick={
// セグメントを再レンダリングすることでリカバリーを試みます
() => reset()
}
>
Try again
</button>
</div>
)
}error.jsはルートセグメントとそのネストされた子要素をReact Error Boundaryでラップします。バウンダリー内でエラーがスローされた場合、errorコンポーネントがフォールバックUIとして表示されます。
補足:
- React DevToolsを使用すると、エラーバウンダリーを切り替えてエラー状態をテストできます。
- エラーを親エラーバウンダリーまでバブルアップさせたい場合は、
errorコンポーネントをレンダリングする際にthrowを使用できます。
リファレンス
Props
error
error.js Client Componentに転送されるErrorオブジェクトのインスタンス。
補足:開発中は、Client Componentに転送された
Errorオブジェクトはシリアライズされ、デバッグを容易にするために元のエラーのmessageを含みます。ただし、本番環境ではこの動作は異なります。エラーに含まれる機密情報が誤ってユーザーに公開されるのを防ぐためです。
error.message
- Client Componentsから転送されたエラーは、元の
Errorメッセージを表示します。 - Server Componentsから転送されたエラーは、識別子を含む汎用メッセージを表示します。これは機密情報の漏洩を防ぐためです。
errors.digestの下にある識別子を使用して、対応するサーバー側ログと照合できます。
error.digest
スローされたエラーの自動生成ハッシュ。サーバー側ログの対応するエラーと照合するために使用できます。
reset
エラーの原因は、時に一時的である場合があります。このような場合、再度試行することでエラーが解決される可能性があります。
エラーコンポーネントはreset()関数を使用して、ユーザーがエラーからのリカバリーを試行するようプロンプトできます。実行時、この関数はエラーバウンダリーのコンテンツを再レンダリングしようとします。成功した場合、フォールバックエラーコンポーネントは再レンダリングの結果に置き換えられます。
'use client' // エラーバウンダリーはClient Componentsである必要があります
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
)
}例
グローバルエラー
あまり一般的ではありませんが、root layoutやテンプレートを使用してルートappディレクトリに配置されたglobal-error.jsxでエラーを処理できます。多言語化を活用している場合も同様です。グローバルエラーUIは、エラーページが必要とする独自の<html>および<body>タグ、グローバルスタイル、フォント、またはその他の依存関係を定義する必要があります。このファイルは、アクティブな場合、root layoutまたはテンプレートの代わりになります。
補足:エラーバウンダリーはClient Componentsである必要があるため、
global-error.jsxではmetadataおよびgenerateMetadataのエクスポートはサポートされていません。代わりに、React<title>コンポーネントを使用できます。
'use client' // エラーバウンダリーはClient Componentsである必要があります
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
// global-errorはhtmlおよびbodyタグを含む必要があります
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}カスタムエラーバウンダリーを使用した適切なエラーリカバリー
クライアント側でレンダリングが失敗した場合、より良いユーザー体験のため、最後に既知のサーバーレンダリング済みUIを表示することが有用です。
GracefullyDegradingErrorBoundaryは、エラー発生前の現在のHTMLをキャプチャして保存するカスタムエラーバウンダリーの例です。レンダリングエラーが発生した場合、キャプチャされたHTMLを再レンダリングし、ユーザーに通知する永続的な通知バーを表示します。
'use client'
import React, { Component, ErrorInfo, ReactNode } from 'react'
interface ErrorBoundaryProps {
children: ReactNode
onError?: (error: Error, errorInfo: ErrorInfo) => void
}
interface ErrorBoundaryState {
hasError: boolean
}
export class GracefullyDegradingErrorBoundary extends Component
ErrorBoundaryProps,
ErrorBoundaryState
> {
private contentRef: React.RefObject<HTMLDivElement | null>
constructor(props: ErrorBoundaryProps) {
super(props)
this.state = { hasError: false }
this.contentRef = React.createRef()
}
static getDerivedStateFromError(_: Error): ErrorBoundaryState {
return { hasError: true }
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
if (this.props.onError) {
this.props.onError(error, errorInfo)
}
}
render() {
if (this.state.hasError) {
// ハイドレーションなしで現在のHTMLコンテンツをレンダリングします
return (
<>
<div
ref={this.contentRef}
suppressHydrationWarning
dangerouslySetInnerHTML={{
__html: this.contentRef.current?.innerHTML || '',
}}
/>
<div className="fixed bottom-0 left-0 right-0 bg-red-600 text-white py-4 px-6 text-center">
<p className="font-semibold">
ページレンダリング中にエラーが発生しました
</p>
</div>
</>
)
}
return <div ref={this.contentRef}>{this.props.children}</div>
}
}
export default GracefullyDegradingErrorBoundaryバージョン履歴
| バージョン | 変更内容 |
|---|---|
v15.2.0 | 開発環境でもglobal-errorを表示するようになりました。 |
v13.1.0 | 導入時期:global-error。 |
v13.0.0 | 導入時期:error。 |