74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
import { useErrorHandler } from './useErrorHandler';
|
|
import { trackLoading } from '../components/common/LoadingStateMonitor';
|
|
|
|
interface UsePageDataLoaderOptions {
|
|
loadFunction: () => Promise<any>;
|
|
componentName: string;
|
|
autoLoad?: boolean;
|
|
dependencies?: any[];
|
|
}
|
|
|
|
export function usePageDataLoader<T = any>({
|
|
loadFunction,
|
|
componentName,
|
|
autoLoad = true,
|
|
dependencies = [],
|
|
}: UsePageDataLoaderOptions) {
|
|
const [data, setData] = useState<T | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const { addError } = useErrorHandler(componentName);
|
|
const loadingKey = `${componentName}-data-loading`;
|
|
const hasLoadedRef = useRef(false);
|
|
|
|
const load = useCallback(async () => {
|
|
setLoading(true);
|
|
setError(null);
|
|
trackLoading(loadingKey, true);
|
|
|
|
try {
|
|
const result = await loadFunction();
|
|
setData(result);
|
|
setError(null);
|
|
return result;
|
|
} catch (err: any) {
|
|
const errorMessage = err.message || 'Failed to load data';
|
|
setError(errorMessage);
|
|
addError(err, componentName);
|
|
throw err;
|
|
} finally {
|
|
setLoading(false);
|
|
trackLoading(loadingKey, false);
|
|
}
|
|
}, [loadFunction, componentName, loadingKey, addError]);
|
|
|
|
useEffect(() => {
|
|
if (autoLoad && !hasLoadedRef.current) {
|
|
hasLoadedRef.current = true;
|
|
load().catch(() => {
|
|
// Error already handled by addError
|
|
});
|
|
}
|
|
}, [autoLoad, load]);
|
|
|
|
// Reload when dependencies change
|
|
useEffect(() => {
|
|
if (autoLoad && hasLoadedRef.current && dependencies.length > 0) {
|
|
load().catch(() => {
|
|
// Error already handled by addError
|
|
});
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, dependencies);
|
|
|
|
return {
|
|
data,
|
|
loading,
|
|
error,
|
|
load,
|
|
reload: load,
|
|
};
|
|
}
|
|
|