Update to SWR version 2.x (#296)
* Update SWR to version 2.1.5 * Improve generic type names * Use "isLoading" property of "useSWR" response * Correctly load library without selected tab With the latest SWR version the library was empty on the first load. Not sure what exactly is the reason, but due to "isPaused" the request wasn't sent even after "activeTab" wasn't undefined anymore. Instead of using "isPaused", passing "null" as the key will also prevent SWR from doing the request.
This commit is contained in:
@@ -46,7 +46,7 @@
|
|||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"react-virtuoso": "^1.8.6",
|
"react-virtuoso": "^1.8.6",
|
||||||
"swr": "^1.3.0",
|
"swr": "^2.1.5",
|
||||||
"use-query-params": "^1.2.3",
|
"use-query-params": "^1.2.3",
|
||||||
"web-vitals": "^2.1.0"
|
"web-vitals": "^2.1.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ const ChapterList: React.FC<IProps> = ({ mangaId }) => {
|
|||||||
const {
|
const {
|
||||||
data: chaptersData,
|
data: chaptersData,
|
||||||
mutate,
|
mutate,
|
||||||
loading,
|
isLoading,
|
||||||
} = useQuery<IChapter[]>(`/api/v1/manga/${mangaId}/chapters?onlineFetch=false`);
|
} = useQuery<IChapter[]>(`/api/v1/manga/${mangaId}/chapters?onlineFetch=false`);
|
||||||
const chapters = useMemo(() => chaptersData ?? [], [chaptersData]);
|
const chapters = useMemo(() => chaptersData ?? [], [chaptersData]);
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ const ChapterList: React.FC<IProps> = ({ mangaId }) => {
|
|||||||
.catch(() => makeToast(t(actionsStrings[action].error, { count: chapterIds.length }) as string, 'error'));
|
.catch(() => makeToast(t(actionsStrings[action].error, { count: chapterIds.length }) as string, 'error'));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export default function MangaExtensions() {
|
|||||||
);
|
);
|
||||||
}, [t, shownLangs]);
|
}, [t, shownLangs]);
|
||||||
|
|
||||||
const { data: allExtensions, mutate, loading } = useQuery<IExtension[]>('/api/v1/extension/list');
|
const { data: allExtensions, mutate, isLoading } = useQuery<IExtension[]>('/api/v1/extension/list');
|
||||||
|
|
||||||
const filteredExtensions = useMemo(
|
const filteredExtensions = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -169,7 +169,7 @@ export default function MangaExtensions() {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (loading) {
|
if (isLoading) {
|
||||||
return <LoadingPlaceholder />;
|
return <LoadingPlaceholder />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export default function Library() {
|
|||||||
|
|
||||||
const { options } = useLibraryOptionsContext();
|
const { options } = useLibraryOptionsContext();
|
||||||
const [lastLibraryUpdate, setLastLibraryUpdate] = useState(Date.now());
|
const [lastLibraryUpdate, setLastLibraryUpdate] = useState(Date.now());
|
||||||
const { data: tabsData, error: tabsError, loading } = useQuery<ICategory[]>('/api/v1/category');
|
const { data: tabsData, error: tabsError, isLoading } = useQuery<ICategory[]>('/api/v1/category');
|
||||||
const tabs = tabsData ?? [];
|
const tabs = tabsData ?? [];
|
||||||
const librarySize = useMemo(() => tabs.map((tab) => tab.size).reduce((prev, curr) => prev + curr, 0), [tabs]);
|
const librarySize = useMemo(() => tabs.map((tab) => tab.size).reduce((prev, curr) => prev + curr, 0), [tabs]);
|
||||||
|
|
||||||
@@ -46,10 +46,8 @@ export default function Library() {
|
|||||||
const {
|
const {
|
||||||
data: mangaData,
|
data: mangaData,
|
||||||
error: mangaError,
|
error: mangaError,
|
||||||
loading: mangaLoading,
|
isLoading: mangaLoading,
|
||||||
} = useQuery<IManga[]>(`/api/v1/category/${activeTab?.id}`, {
|
} = useQuery<IManga[]>(activeTab ? `/api/v1/category/${activeTab?.id}` : null);
|
||||||
isPaused: () => activeTab == null,
|
|
||||||
});
|
|
||||||
const mangas = mangaData ?? [];
|
const mangas = mangaData ?? [];
|
||||||
|
|
||||||
const { setTitle, setAction } = useContext(NavbarContext);
|
const { setTitle, setAction } = useContext(NavbarContext);
|
||||||
@@ -88,7 +86,7 @@ export default function Library() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loading) {
|
if (isLoading) {
|
||||||
return <LoadingPlaceholder />;
|
return <LoadingPlaceholder />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const Manga: React.FC = () => {
|
|||||||
const {
|
const {
|
||||||
data: manga,
|
data: manga,
|
||||||
error,
|
error,
|
||||||
loading,
|
isLoading,
|
||||||
isValidating,
|
isValidating,
|
||||||
mutate,
|
mutate,
|
||||||
} = useQuery<IManga>(`/api/v1/manga/${id}/?onlineFetch=false`);
|
} = useQuery<IManga>(`/api/v1/manga/${id}/?onlineFetch=false`);
|
||||||
@@ -95,7 +95,7 @@ const Manga: React.FC = () => {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</NavbarToolbar>
|
</NavbarToolbar>
|
||||||
|
|
||||||
{loading && <LoadingPlaceholder />}
|
{isLoading && <LoadingPlaceholder />}
|
||||||
|
|
||||||
{manga && <MangaDetails manga={manga} />}
|
{manga && <MangaDetails manga={manga} />}
|
||||||
<ChapterList mangaId={id} />
|
<ChapterList mangaId={id} />
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export default function Sources() {
|
|||||||
const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownSourceLangs', sourceDefualtLangs());
|
const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownSourceLangs', sourceDefualtLangs());
|
||||||
const [showNsfw] = useLocalStorage<boolean>('showNsfw', true);
|
const [showNsfw] = useLocalStorage<boolean>('showNsfw', true);
|
||||||
|
|
||||||
const { data: sources, loading } = useQuery<ISource[]>('/api/v1/source/list');
|
const { data: sources, isLoading } = useQuery<ISource[]>('/api/v1/source/list');
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ export default function Sources() {
|
|||||||
);
|
);
|
||||||
}, [t, shownLangs, sources]);
|
}, [t, shownLangs, sources]);
|
||||||
|
|
||||||
if (loading) return <LoadingPlaceholder />;
|
if (isLoading) return <LoadingPlaceholder />;
|
||||||
|
|
||||||
if (sources?.length === 0) {
|
if (sources?.length === 0) {
|
||||||
return <h3>{t('source.error.label.no_sources_found')}</h3>;
|
return <h3>{t('source.error.label.no_sources_found')}</h3>;
|
||||||
|
|||||||
@@ -77,13 +77,13 @@ export default function LibrarySettings() {
|
|||||||
setAction(null);
|
setAction(null);
|
||||||
}, [t]);
|
}, [t]);
|
||||||
|
|
||||||
const { data: categories, loading, error: requestError, mutate } = useQuery<ICategory[]>('/api/v1/category/');
|
const { data: categories, isLoading, error: requestError, mutate } = useQuery<ICategory[]>('/api/v1/category/');
|
||||||
|
|
||||||
const [currentCategories, setCurrentCategories] = useState<ICategory[]>(categories ?? []); // categories to check if response categories changed
|
const [currentCategories, setCurrentCategories] = useState<ICategory[]>(categories ?? []); // categories to check if response categories changed
|
||||||
const [dialogCategories, setDialogCategories] = useState<ICategory[]>(categories ?? []); // categories that are shown and updated in the dialog
|
const [dialogCategories, setDialogCategories] = useState<ICategory[]>(categories ?? []); // categories that are shown and updated in the dialog
|
||||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||||
|
|
||||||
const retrievedCategoriesChanged = !loading && categories?.length && categories !== currentCategories;
|
const retrievedCategoriesChanged = !isLoading && categories?.length && categories !== currentCategories;
|
||||||
if (retrievedCategoriesChanged) {
|
if (retrievedCategoriesChanged) {
|
||||||
setCurrentCategories(categories);
|
setCurrentCategories(categories);
|
||||||
setDialogCategories(categories);
|
setDialogCategories(categories);
|
||||||
|
|||||||
@@ -46,13 +46,7 @@ export async function fetcher<T = any>(path: string) {
|
|||||||
return res.data as T;
|
return res.data as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useQuery = <D extends any = any, E extends any = any>(
|
export const useQuery = <Data extends any = any, Error extends any = any>(
|
||||||
key: string,
|
key: string | null,
|
||||||
config?: SWRConfiguration<D, E>,
|
config?: SWRConfiguration<Data, Error>,
|
||||||
): SWRResponse<D, E> & { loading: boolean } => {
|
): SWRResponse<Data, Error> => useSWR(key, config);
|
||||||
const res = useSWR(key, config);
|
|
||||||
return {
|
|
||||||
...res,
|
|
||||||
loading: res.data == null && res.error == null,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ export const useDefaultReaderSettings = (): {
|
|||||||
settings: IReaderSettings;
|
settings: IReaderSettings;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
} => {
|
} => {
|
||||||
const { data: meta, loading } = useQuery<Metadata>('/api/v1/meta');
|
const { data: meta, isLoading } = useQuery<Metadata>('/api/v1/meta');
|
||||||
const settings = getReaderSettingsWithDefaultValueFallback<IReaderSettings>(meta);
|
const settings = getReaderSettingsWithDefaultValueFallback<IReaderSettings>(meta);
|
||||||
|
|
||||||
return { metadata: meta, settings, loading };
|
return { metadata: meta, settings, loading: isLoading };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ export const useSearchSettings = (): {
|
|||||||
settings: ISearchSettings;
|
settings: ISearchSettings;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
} => {
|
} => {
|
||||||
const { data: meta, loading } = useQuery<Metadata>('/api/v1/meta');
|
const { data: meta, isLoading } = useQuery<Metadata>('/api/v1/meta');
|
||||||
const settings = getSearchSettingsWithDefaultValueFallback(meta);
|
const settings = getSearchSettingsWithDefaultValueFallback(meta);
|
||||||
|
|
||||||
return { metadata: meta, settings, loading };
|
return { metadata: meta, settings, loading: isLoading };
|
||||||
};
|
};
|
||||||
|
|||||||
15
yarn.lock
15
yarn.lock
@@ -10199,10 +10199,12 @@ svgo@^2.7.0:
|
|||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
stable "^0.1.8"
|
stable "^0.1.8"
|
||||||
|
|
||||||
swr@^1.3.0:
|
swr@^2.1.5:
|
||||||
version "1.3.0"
|
version "2.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8"
|
resolved "https://registry.yarnpkg.com/swr/-/swr-2.1.5.tgz#688effa719c03f6d35c66decbb0f8e79c7190399"
|
||||||
integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==
|
integrity sha512-/OhfZMcEpuz77KavXST5q6XE9nrOBOVcBLWjMT+oAE/kQHyE3PASrevXCtQDZ8aamntOfFkbVJp7Il9tNBQWrw==
|
||||||
|
dependencies:
|
||||||
|
use-sync-external-store "^1.2.0"
|
||||||
|
|
||||||
symbol-tree@^3.2.4:
|
symbol-tree@^3.2.4:
|
||||||
version "3.2.4"
|
version "3.2.4"
|
||||||
@@ -10591,6 +10593,11 @@ use-query-params@^1.2.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
serialize-query-params "^1.3.5"
|
serialize-query-params "^1.3.5"
|
||||||
|
|
||||||
|
use-sync-external-store@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
|
||||||
|
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||||
|
|
||||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
|||||||
Reference in New Issue
Block a user