Split long useEffect in useGenealogyLoader

This commit is contained in:
Przemek Więch
2026-06-24 16:49:18 +02:00
parent 445009a89b
commit 6c8a716ed0

View File

@@ -195,43 +195,29 @@ export function useGenealogyLoader(options: {
loadedSelectionRef.current = undefined; loadedSelectionRef.current = undefined;
}, []); }, []);
// Main data loading and updating side-effect const shouldTriggerNewLoad = useCallback(
useEffect(() => { (newSourceSpec: DataSourceSpec, newSelection?: IndiInfo) => {
(async () => { return (
if (location.pathname !== '/view') {
if (state !== AppState.INITIAL) {
setState(AppState.INITIAL);
}
setData(undefined);
return;
}
const args = getArguments(location);
if (!args.sourceSpec) {
navigate({pathname: '/'}, {replace: true});
return;
}
if (
(state === AppState.INITIAL || (state === AppState.INITIAL ||
isNewData(args.sourceSpec, args.selection)) && isNewData(newSourceSpec, newSelection)) &&
state !== AppState.LOADING && state !== AppState.LOADING &&
state !== AppState.LOADING_MORE state !== AppState.LOADING_MORE
) { );
},
[state, isNewData],
);
const triggerNewLoad = useCallback(
async (newSourceSpec: DataSourceSpec, newSelection?: IndiInfo) => {
setState(AppState.LOADING); setState(AppState.LOADING);
setSourceSpec(args.sourceSpec); setSourceSpec(newSourceSpec);
loadedSelectionRef.current = args.selection; loadedSelectionRef.current = newSelection;
const currentFetchId = ++fetchIdRef.current; const currentFetchId = ++fetchIdRef.current;
setLoadingStatus('Loading…'); setLoadingStatus('Loading…');
try { try {
const data = await loadData( const data = await loadData(newSourceSpec, newSelection, (status) => {
args.sourceSpec,
args.selection,
(status) => {
if (isMountedRef.current) setLoadingStatus(status); if (isMountedRef.current) setLoadingStatus(status);
}, });
);
if (!isMountedRef.current || fetchIdRef.current !== currentFetchId) { if (!isMountedRef.current || fetchIdRef.current !== currentFetchId) {
return; return;
} }
@@ -239,54 +225,54 @@ export function useGenealogyLoader(options: {
`Rendering chart (${data.chartData.indis.length.toLocaleString()} people)…`, `Rendering chart (${data.chartData.indis.length.toLocaleString()} people)…`,
); );
setData(data); setData(data);
loadedSelectionRef.current = getSelection( loadedSelectionRef.current = getSelection(data.chartData, newSelection);
data.chartData,
args.selection,
);
setState(AppState.SHOWING_CHART); setState(AppState.SHOWING_CHART);
} catch (error: unknown) { } catch (error: unknown) {
if (!isMountedRef.current || fetchIdRef.current !== currentFetchId) { if (!isMountedRef.current || fetchIdRef.current !== currentFetchId) {
return; return;
} }
if (error instanceof GoogleDriveAuthError) { if (error instanceof GoogleDriveAuthError) {
if (args.sourceSpec.source === DataSourceEnum.GOOGLE_DRIVE) { if (newSourceSpec.source === DataSourceEnum.GOOGLE_DRIVE) {
onAuthError((args.sourceSpec as GoogleDriveSourceSpec).fileId); onAuthError((newSourceSpec as GoogleDriveSourceSpec).fileId);
} }
} else { } else {
setErrorMessage(getI18nMessage(error as Error, intl)); setErrorMessage(getI18nMessage(error as Error, intl));
} }
} }
} else if ( },
state === AppState.SHOWING_CHART || [intl, loadData, onAuthError, setErrorMessage],
state === AppState.LOADING_MORE
) {
const loadMoreFromWikitree =
args.sourceSpec.source === DataSourceEnum.WIKITREE &&
!!args.selection &&
(!loadedSelectionRef.current ||
loadedSelectionRef.current.id !== args.selection.id);
setState(
loadMoreFromWikitree ? AppState.LOADING_MORE : AppState.SHOWING_CHART,
); );
if (loadMoreFromWikitree && args.selection) {
const shouldTriggerWikiTreeLoadMore = useCallback(
(newSourceSpec: DataSourceSpec, newSelection?: IndiInfo) => {
if (state !== AppState.SHOWING_CHART && state !== AppState.LOADING_MORE) {
return false;
}
return (
newSourceSpec.source === DataSourceEnum.WIKITREE &&
!!newSelection &&
(!loadedSelectionRef.current ||
loadedSelectionRef.current.id !== newSelection.id)
);
},
[state],
);
const triggerWikiTreeLoadMore = useCallback(
async (selection: IndiInfo) => {
setState(AppState.LOADING_MORE);
const currentFetchId = ++fetchIdRef.current; const currentFetchId = ++fetchIdRef.current;
try { try {
const data = await loadWikiTree(args.selection.id, intl); const data = await loadWikiTree(selection.id, intl);
if ( if (!isMountedRef.current || fetchIdRef.current !== currentFetchId) {
!isMountedRef.current ||
fetchIdRef.current !== currentFetchId
) {
return; return;
} }
const newSelection = getSelection(data.chartData, args.selection); const newSelection = getSelection(data.chartData, selection);
setData(data); setData(data);
loadedSelectionRef.current = newSelection; loadedSelectionRef.current = newSelection;
setState(AppState.SHOWING_CHART); setState(AppState.SHOWING_CHART);
} catch (error: unknown) { } catch (error: unknown) {
if ( if (!isMountedRef.current || fetchIdRef.current !== currentFetchId) {
!isMountedRef.current ||
fetchIdRef.current !== currentFetchId
) {
return; return;
} }
setState(AppState.SHOWING_CHART); setState(AppState.SHOWING_CHART);
@@ -300,20 +286,44 @@ export function useGenealogyLoader(options: {
), ),
); );
} }
},
[intl, displayErrorPopup],
);
// Main data loading and updating side-effect
useEffect(() => {
if (location.pathname !== '/view') {
if (state !== AppState.INITIAL) {
setState(AppState.INITIAL);
} }
setData(undefined);
return;
}
const args = getArguments(location);
if (!args.sourceSpec) {
navigate({pathname: '/'}, {replace: true});
return;
}
if (shouldTriggerNewLoad(args.sourceSpec, args.selection)) {
triggerNewLoad(args.sourceSpec, args.selection);
} else if (
shouldTriggerWikiTreeLoadMore(args.sourceSpec, args.selection) &&
args.selection
) {
triggerWikiTreeLoadMore(args.selection);
} else if (state === AppState.LOADING_MORE) {
setState(AppState.SHOWING_CHART);
} }
})();
}, [ }, [
location, location,
state, state,
data,
navigate, navigate,
intl, shouldTriggerNewLoad,
isNewData, triggerNewLoad,
loadData, shouldTriggerWikiTreeLoadMore,
onAuthError, triggerWikiTreeLoadMore,
setErrorMessage,
displayErrorPopup,
]); ]);
// Clean up object URLs created for uploaded images/files when the dataset // Clean up object URLs created for uploaded images/files when the dataset