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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user