Reactでルーティングの実装
hebishima.shogo
プログラマーのあれこれ
はい、hebiです。
Reactの集約エラーハンドラーとなるErrorBoundaryを作ってみました。
react-error-boundaryを利用して作ろうかなと思いましたが、少しクセが強かったので、自前で作成しました。
完成形です。
import { useState, useEffect, ReactNode } from "react";
import { useNavigate } from "react-router-dom";
type ErrorBoundaryProps = {
children: ReactNode;
};
function useErrorBoundary(): [boolean, ErrorEvent | null] {
const [hasError, setHasError] = useState(false);
const [errorEvent, setErrorEvent] = useState<ErrorEvent | null>(null);
useEffect(() => {
const errorHandler = (e: ErrorEvent) => {
setHasError(true);
setErrorEvent(e);
};
// エラーハンドラを設定
window.addEventListener("error", errorHandler);
return () => {
// コンポーネントがアンマウントされる際にエラーハンドラをクリーンアップ
window.removeEventListener("error", errorHandler);
};
}, []);
return [hasError, errorEvent];
}
function ErrorBoundary({ children }: ErrorBoundaryProps) {
const [hasError, errorEvent] = useErrorBoundary();
const navigate = useNavigate();
if (hasError) {
const errorInfo = {
message: errorEvent?.message,
filename: errorEvent?.filename,
lineno: errorEvent?.lineno,
colno: errorEvent?.colno,
};
// エラーページへの遷移
navigate("/error", {
state: errorInfo,
});
return <></>;
}
// エラーがない場合は、通常のコンポーネントを描画。
return <>{children}</>;
}
export default ErrorBoundary;
コンポーネント内で例外が発生するとwindow.addEventListener(“error”, errorHandler)で設定したerrorHandler関数が実行されます。
useErrorBoundary()がhasError, errorEventを返却するので、hasErrorがtrueの場合は、エラーページへ遷移します。
注意点として、react-error-boundaryを利用した場合も同じですが、非同期処理内で例外が発生した場合はキャッチされません。try-catchでthrowするか、then-catchの場合は、以下のようにスローすることでキャッチされることを確認してます。(try-catchでもsetStateが必要かも?要確認。)
const [, setState] = useState(null);
setState(() => {
throw e;
});
以上です。最後までお読みいただきありがとうございました。