Skip to content

Commit

Permalink
fix: axios cancel alternative not working (#236)
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsobries authored Oct 17, 2023
1 parent 28010ba commit a10d997
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 158 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
"react-resize-detector": "^8.1.0",
"react-sortablejs": "^6.1.4",
"react-table": "^7.8.0",
"react-use-cancel-token": "^1.0.3",
"sortablejs": "^1.15.0",
"string-hash": "^1.1.3",
"tailwind-merge": "^1.14.0",
Expand Down
215 changes: 98 additions & 117 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

28 changes: 22 additions & 6 deletions resources/js/Components/Galleries/Hooks/useGalleryNtfs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { groupBy } from "@ardenthq/sdk-helpers";
import axios from "axios";
import { useMemo, useState } from "react";
import useAbortController from "react-use-cancel-token";
import GalleryNftData = App.Data.Gallery.GalleryNftData;
import { type CollectionsPageMeta, type GalleryNftsState } from "@/Components/Galleries/Hooks/useGalleryNftsContext";
import { isTruthy } from "@/Utils/is-truthy";
Expand Down Expand Up @@ -47,6 +48,7 @@ export const useGalleryNtfs = ({
}: GalleryNftsProperties): GalleryNftsState => {
const [loadingCollections, setLoadingCollections] = useState(false);
const [isSearchingCollections, setIsSearchingCollections] = useState(false);
const { newAbortSignal, cancelPreviousRequest, isCancel } = useAbortController();

const [nfts, setNfts] = useState<GalleryNftData[]>(loadedNfts);

Expand Down Expand Up @@ -149,7 +151,9 @@ export const useGalleryNtfs = ({
}
};

const fetchCollections = async (nextPageUrl: string, query?: string): Promise<CollectionsResponse> => {
const fetchCollections = async (nextPageUrl: string, query?: string): Promise<void> => {
cancelPreviousRequest();

setLoadingCollections(true);

// let url = new URLSearchParams(nextPageUrl);
Expand All @@ -159,9 +163,23 @@ export const useGalleryNtfs = ({
url.searchParams.append("query", query);
}

const { data } = await axios.get<CollectionsResponse>(decodeURIComponent(url.toString()), {
requestId: "gallery-page",
});
let data: CollectionsResponse;

try {
const response = await axios.get<CollectionsResponse>(decodeURIComponent(url.toString()), {
signal: newAbortSignal(),
});

data = response.data;
} catch (error) {
/* istanbul ignore next -- @preserve */
if (isCancel(error)) {
return;
}

/* istanbul ignore next -- @preserve */
throw error;
}

setPageMeta(data.collections.paginated.meta);

Expand All @@ -179,8 +197,6 @@ export const useGalleryNtfs = ({
setNfts([...existingNfts, ...data.nfts]);

setLoadingCollections(false);

return data;
};

const searchNfts = async (query?: string): Promise<void> => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import axios from "axios";
import { useCallback, useState } from "react";
import useAbortController from "react-use-cancel-token";
import TokenListItemData = App.Data.TokenListItemData;
import { useLiveSearch } from "@/Hooks/useLiveSearch";
import { isTruthy } from "@/Utils/is-truthy";
Expand All @@ -19,9 +20,13 @@ interface UseAssetsProperties {
export const useAssets = ({ initialAssets, onSearchError }: UseAssetsProperties): UseAssetsState => {
const [assets, setAssets] = useState<TokenListItemData[]>(initialAssets);

const { newAbortSignal, cancelPreviousRequest } = useAbortController();

const searchTokens = async (query: string): Promise<void> => {
cancelPreviousRequest();
// The `useAbortController@isCancel` exception handling is done on the `useLiveSearch` hook.
const { data } = await axios.get<App.Data.TokenListItemData[]>(route("tokens.search", { query }), {
requestId: "search-tokens",
signal: newAbortSignal(),
});
setAssets(data);
};
Expand Down
5 changes: 3 additions & 2 deletions resources/js/Hooks/useLiveSearch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from "axios";
import { useCallback, useEffect, useState } from "react";
import useAbortController from "react-use-cancel-token";
import { replaceUrlQuery } from "@/Utils/replace-url-query";

const THROTTLE_TIMEOUT = 500;
Expand All @@ -23,6 +23,7 @@ export const useLiveSearch = <T>({
const [query, setQuery] = useState(queryParameter);
const [throttledQuery, setThrottledQuery] = useState<string>(queryParameter);
const [searchedQuery, setSearchedQuery] = useState<string>(queryParameter);
const { isCancel } = useAbortController();

const doSearch = useCallback(
async (searchQuery: string): Promise<void> => {
Expand All @@ -48,7 +49,7 @@ export const useLiveSearch = <T>({
// This is done to allow the component using this hook to assign the
// results to a state before changing the state to "not loading".
} catch (error) {
if (!axios.isCancel(error)) {
if (!isCancel(error)) {
onError?.(error);
}

Expand Down
7 changes: 6 additions & 1 deletion resources/js/Pages/Collections/Hooks/useCollections.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isNumber } from "@ardenthq/sdk-helpers";
import axios from "axios";
import { useCallback, useRef, useState } from "react";
import useAbortController from "react-use-cancel-token";
import { type PaginationData } from "@/Components/Pagination/Pagination.contracts";
import { useInertiaHeader } from "@/Hooks/useInertiaHeader";
import { useLiveSearch } from "@/Hooks/useLiveSearch";
Expand Down Expand Up @@ -72,6 +73,8 @@ export const useCollections = ({
sortBy: string | null;
onSearchError: (error: unknown) => void;
}): CollectionsState => {
const { newAbortSignal, cancelPreviousRequest } = useAbortController();

const [isLoading, setIsLoading] = useState(true);
const isLoadingMore = useRef(false);
const [collections, setCollections] = useState<App.Data.Collections.CollectionData[]>([]);
Expand All @@ -96,6 +99,7 @@ export const useCollections = ({
showHidden = false,
sort = null,
}: QueryParameters = {}): Promise<CollectionsResponse> => {
cancelPreviousRequest();
setIsLoading(true);
isLoadingMore.current = true;

Expand All @@ -111,8 +115,9 @@ export const useCollections = ({
pageUrlWithSearch += `&chain=${selectedChainIds.join(",")}`;
}

// The `useAbortController@isCancel` exception handling is done on the `useLiveSearch` hook.
const { data } = await axios.get<CollectionsResponse>(pageUrlWithSearch, {
requestId: "collections-page",
signal: newAbortSignal(),
headers,
});

Expand Down
14 changes: 5 additions & 9 deletions resources/js/Pages/Collections/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,6 @@ const CollectionsIndex = ({
},
});

useEffect(() => {
if (!auth.authenticated) {
return;
}

reload();
}, [auth.authenticated]);

const selectDisplayTypeHandler = (displayType: CollectionDisplayType): void => {
setDisplayType(displayType);

Expand All @@ -107,8 +99,12 @@ const CollectionsIndex = ({
};

useEffect(() => {
if (!auth.authenticated) {
return;
}

reload({ selectedChainIds });
}, [selectedChainIds]);
}, [selectedChainIds, auth.authenticated]);

return (
<DefaultLayout toastMessage={props.toast}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Head, router } from "@inertiajs/react";
import axios from "axios";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import useAbortController from "react-use-cancel-token";
import { EmptyBlock } from "@/Components/EmptyBlock/EmptyBlock";
import { SearchInput } from "@/Components/Form/SearchInput";
import { Heading } from "@/Components/Heading";
Expand All @@ -27,6 +28,7 @@ export const GalleryPage = ({
}): JSX.Element => {
const { t } = useTranslation();

const { newAbortSignal, cancelPreviousRequest, isCancel } = useAbortController();
const [loading, setLoading] = useState(true);

const searchParameters = new URLSearchParams(window.location.search);
Expand All @@ -43,19 +45,35 @@ export const GalleryPage = ({
const { headers } = useInertiaHeader();

const fetchGalleries = async (): Promise<void> => {
cancelPreviousRequest();

const pageUrlWithSearch = replaceUrlQuery({
query: debouncedQuery,
page: (debouncedQuery !== initialQuery ? 1 : currentPage).toString(),
});

setLoading(true);

const { data } = await axios.get<{
let data: {
paginated: PaginationData<App.Data.Gallery.GalleryData>;
}>(pageUrlWithSearch, {
requestId: "gallery-page",
headers,
});
};

try {
const reponse = await axios.get<{
paginated: PaginationData<App.Data.Gallery.GalleryData>;
}>(pageUrlWithSearch, {
headers,
signal: newAbortSignal(),
});

data = reponse.data;
} catch (error) {
if (isCancel(error)) {
return;
}

throw error;
}

// If the user is on a page that doesn't exist anymore, redirect them to the last page
if (data.paginated.meta.current_page > data.paginated.meta.last_page) {
Expand All @@ -66,6 +84,7 @@ export const GalleryPage = ({
}

setGalleries(data.paginated);

setLoading(false);
};

Expand Down
13 changes: 1 addition & 12 deletions resources/js/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,13 @@ import { i18n } from "@/I18n";
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
(window as any).CookieConsent = CookieConsent;

const abortController = new AbortController();
const { signal } = abortController;

axios.interceptors.request.use((config) => {
config.signal = signal;
return config;
});

axios.interceptors.response.use(
(response) => response,
async (error: AxiosError) => {
const { status } = error.response ?? {};

if (status === 419) {
abortController.abort();
await axios.get(route("refresh-csrf-token"), {
signal,
});
await axios.get(route("refresh-csrf-token"));

if (error.response != null) {
return await axios(error.response.config);
Expand Down
5 changes: 0 additions & 5 deletions resources/types/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import ziggyRoute from "ziggy-js";
import { AxiosInstance, AxiosRequestConfig } from "axios";
import { Ethereum } from "@/hooks/useMetaMask.contracts";

declare module "axios" {
export interface AxiosRequestConfig {
requestId?: string;
}
}
declare global {
const route: typeof ziggyRoute;

Expand Down

0 comments on commit a10d997

Please sign in to comment.