import { useEffect, useState } from 'react'; export interface UseDelayedErrorDisplayOptions { error: Error | null; isLoading: boolean; delayMs?: number; // デフォルト90000ms (90秒) } export interface UseDelayedErrorDisplayResult { shouldShowError: boolean; shouldShowLoading: boolean; delayedError: Error | null; } /** * エラー発生後も指定時間(デフォルト90秒)はローディング表示を継続し、 * 時間経過後にエラーを表示するHook * * @param options エラー、ローディング状態、遅延時間(ミリ秒) * @returns エラー表示すべきか、ローディング表示すべきか、遅延後のエラー */ export function useDelayedErrorDisplay({ error, isLoading, delayMs = 90000, // 90秒(本番設定) }: UseDelayedErrorDisplayOptions): UseDelayedErrorDisplayResult { const [errorTimestamp, setErrorTimestamp] = useState(null); const [shouldShowError, setShouldShowError] = useState(false); // エラーが発生した時刻を記録 useEffect(() => { if (error && !errorTimestamp) { setErrorTimestamp(Date.now()); setShouldShowError(false); } else if (!error) { // エラーがクリアされた場合はリセット setErrorTimestamp(null); setShouldShowError(false); } }, [error, errorTimestamp]); // 指定時間経過後にエラーを表示 useEffect(() => { if (!errorTimestamp || !error || shouldShowError) { // すでにエラー表示状態の場合は何もしない return; } const checkElapsed = () => { const elapsed = Date.now() - errorTimestamp; if (elapsed >= delayMs) { setShouldShowError(true); } }; // 初回チェック checkElapsed(); // 1秒ごとにチェック const interval = setInterval(checkElapsed, 1000); return () => clearInterval(interval); }, [errorTimestamp, error, delayMs, shouldShowError]); // ローディング表示判定: // - 通常ローディング中、または // - エラーが発生しているが、まだ遅延時間内 const shouldShowLoading = isLoading || (error !== null && errorTimestamp !== null && !shouldShowError); return { shouldShowError, shouldShowLoading, delayedError: shouldShowError ? error : null, }; }