Fix retry of failed source searches

Regression introduced with 5aec8282cb (brain fart).
The abortRequest function changes everytime, thus the useEffect was triggered on every render...
This commit is contained in:
schroda
2024-10-07 13:07:57 +02:00
parent 5aec8282cb
commit cd7ec05ce3
2 changed files with 31 additions and 37 deletions

View File

@@ -9,7 +9,7 @@
import Card from '@mui/material/Card'; import Card from '@mui/material/Card';
import CardActionArea from '@mui/material/CardActionArea'; import CardActionArea from '@mui/material/CardActionArea';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import React, { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useState } from 'react'; import React, { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { Link, useLocation } from 'react-router-dom'; import { Link, useLocation } from 'react-router-dom';
import { StringParam, useQueryParam } from 'use-query-params'; import { StringParam, useQueryParam } from 'use-query-params';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -110,12 +110,24 @@ const SourceSearchPreview = React.memo(
const { t } = useTranslation(); const { t } = useTranslation();
const { id, displayName, lang } = source; const { id, displayName, lang } = source;
const currentSearchString = useRef(searchString);
const currentAbortRequest = useRef<(reason: any) => void>(() => {});
const didSearchChange = currentSearchString.current !== searchString;
if (didSearchChange) {
currentSearchString.current = searchString;
currentAbortRequest.current(new Error(`SourceSearchPreview(${id}, ${displayName}): search string changed`));
}
const [refetch, results] = requestManager.useSourceSearch(id, searchString ?? '', undefined, 1, { const [refetch, results] = requestManager.useSourceSearch(id, searchString ?? '', undefined, 1, {
skipRequest: !searchString, skipRequest: !searchString,
addAbortSignal: true, addAbortSignal: true,
}); });
console.log('SearchAll', source.displayName, results);
const { data: searchResult, isLoading, error, abortRequest } = results[0]!; const { data: searchResult, isLoading, error, abortRequest } = results[0]!;
currentAbortRequest.current = abortRequest;
const mangas = searchResult?.fetchSourceManga?.mangas ?? []; const mangas = searchResult?.fetchSourceManga?.mangas ?? [];
const noMangasFound = !error && !isLoading && !mangas.length; const noMangasFound = !error && !isLoading && !mangas.length;
@@ -130,16 +142,6 @@ const SourceSearchPreview = React.memo(
errorMessage = t('manga.error.label.no_mangas_found'); errorMessage = t('manga.error.label.no_mangas_found');
} }
useEffect(
() => () => {
// INFO:
// with strict mode + dev mode the first request will be aborted. due to using SWR there won't be an
// immediate second request since it's the same key. instead the "second" request will be the error handling of SWR
abortRequest(new Error(`SourceSearchPreview(${id}, ${displayName}): search string changed`));
},
[searchString, abortRequest],
);
if ((!isLoading && !searchString) || emptyQuery) { if ((!isLoading && !searchString) || emptyQuery) {
return null; return null;
} }

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
import { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useState } from 'react'; import { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useParams, useNavigate, useLocation } from 'react-router-dom'; import { useParams, useNavigate, useLocation } from 'react-router-dom';
import IconButton from '@mui/material/IconButton'; import IconButton from '@mui/material/IconButton';
import SettingsIcon from '@mui/icons-material/Settings'; import SettingsIcon from '@mui/icons-material/Settings';
@@ -212,11 +212,6 @@ export function SourceMangas() {
clearCache: boolean; clearCache: boolean;
}>().state ?? {}; }>().state ?? {};
const [isFirstRender, setIsFirstRender] = useState(true);
useEffect(() => {
setIsFirstRender(false);
}, []);
const { const {
settings: { hideLibraryEntries }, settings: { hideLibraryEntries },
} = useMetadataServerSettings(); } = useMetadataServerSettings();
@@ -241,6 +236,21 @@ export function SourceMangas() {
query ? SourceContentType.SEARCH : currentContentType!, query ? SourceContentType.SEARCH : currentContentType!,
); );
const scrollToTop = useCallback(() => {
AppStorage.session.setItem(getGridSnapshotKey(location), undefined, false);
window.scrollTo(0, 0);
}, [locationKey]);
const currentQuery = useRef(query);
const currentAbortRequest = useRef<(reason: any) => void>(() => {});
const didSearchChange = currentQuery.current !== query;
if (didSearchChange && contentType === SourceContentType.SEARCH) {
currentQuery.current = query;
currentAbortRequest.current(new Error(`SourceMangas(${sourceId}): search string changed`));
scrollToTop();
}
useEffect( useEffect(
() => () => { () => () => {
setCurrentFiltersToApply(undefined); setCurrentFiltersToApply(undefined);
@@ -249,11 +259,6 @@ export function SourceMangas() {
[sourceId], [sourceId],
); );
const scrollToTop = useCallback(() => {
AppStorage.session.setItem(getGridSnapshotKey(location), undefined, false);
window.scrollTo(0, 0);
}, [locationKey]);
const setFiltersToApply = (filters: IPos[]) => { const setFiltersToApply = (filters: IPos[]) => {
setCurrentFiltersToApply(filters); setCurrentFiltersToApply(filters);
setLocationFiltersToApply(filters); setLocationFiltersToApply(filters);
@@ -269,6 +274,7 @@ export function SourceMangas() {
loadPage, loadPage,
{ data, error, isLoading: loading, size: lastPageNum, abortRequest, filteredOutAllItemsOfFetchedPage }, { data, error, isLoading: loading, size: lastPageNum, abortRequest, filteredOutAllItemsOfFetchedPage },
] = useSourceManga(sourceId, contentType, query, filtersToApply, 1, hideLibraryEntries); ] = useSourceManga(sourceId, contentType, query, filtersToApply, 1, hideLibraryEntries);
currentAbortRequest.current = abortRequest;
const isLoading = loading || filteredOutAllItemsOfFetchedPage; const isLoading = loading || filteredOutAllItemsOfFetchedPage;
const mangas = data?.fetchSourceManga?.mangas ?? []; const mangas = data?.fetchSourceManga?.mangas ?? [];
const hasNextPage = !!data?.fetchSourceManga?.hasNextPage; const hasNextPage = !!data?.fetchSourceManga?.hasNextPage;
@@ -389,20 +395,6 @@ export function SourceMangas() {
requestManager.clearBrowseCacheFor(sourceId); requestManager.clearBrowseCacheFor(sourceId);
}, [clearCache]); }, [clearCache]);
useEffect(
() => () => {
if (contentType !== SourceContentType.SEARCH || isFirstRender) {
return;
}
// INFO:
// with strict mode + dev mode the first request will be aborted. due to using SWR there won't be an
// immediate second request since it's the same key. instead the "second" request will be the error handling of SWR
abortRequest(new Error(`SourceMangas(${sourceId}): search string changed`));
scrollToTop();
},
[query, abortRequest],
);
useLayoutEffect(() => { useLayoutEffect(() => {
setTitle(source?.displayName ?? t('source.title_one')); setTitle(source?.displayName ?? t('source.title_one'));
setAction( setAction(