64 lines
1.5 KiB
TypeScript
64 lines
1.5 KiB
TypeScript
import { useState, useCallback, useEffect } from 'react';
|
|
|
|
interface ErrorInfo {
|
|
message: string;
|
|
source: string;
|
|
timestamp: number;
|
|
stack?: string;
|
|
}
|
|
|
|
const globalErrors: ErrorInfo[] = [];
|
|
const listeners = new Set<(errors: ErrorInfo[]) => void>();
|
|
|
|
export function useErrorHandler(componentName: string) {
|
|
const [errors, setErrors] = useState<ErrorInfo[]>([]);
|
|
|
|
useEffect(() => {
|
|
const updateErrors = () => {
|
|
setErrors([...globalErrors]);
|
|
};
|
|
listeners.add(updateErrors);
|
|
updateErrors();
|
|
|
|
return () => {
|
|
listeners.delete(updateErrors);
|
|
};
|
|
}, []);
|
|
|
|
const addError = useCallback((error: Error | string, source?: string) => {
|
|
const errorInfo: ErrorInfo = {
|
|
message: error instanceof Error ? error.message : error,
|
|
source: source || componentName,
|
|
timestamp: Date.now(),
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
};
|
|
|
|
globalErrors.push(errorInfo);
|
|
// Keep only last 10 errors
|
|
if (globalErrors.length > 10) {
|
|
globalErrors.shift();
|
|
}
|
|
|
|
listeners.forEach(listener => listener([...globalErrors]));
|
|
console.error(`[${errorInfo.source}]`, errorInfo);
|
|
}, [componentName]);
|
|
|
|
const clearError = useCallback((index: number) => {
|
|
globalErrors.splice(index, 1);
|
|
listeners.forEach(listener => listener([...globalErrors]));
|
|
}, []);
|
|
|
|
const clearAllErrors = useCallback(() => {
|
|
globalErrors.length = 0;
|
|
listeners.forEach(listener => listener([]));
|
|
}, []);
|
|
|
|
return {
|
|
errors,
|
|
addError,
|
|
clearError,
|
|
clearAllErrors,
|
|
};
|
|
}
|
|
|