Skip to content

Commit

Permalink
Navigating through lists breaks native browser navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
isstuev committed Jan 2, 2025
1 parent 76c74d5 commit 5437124
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 2 deletions.
52 changes: 51 additions & 1 deletion ui/shared/pagination/useQueryWithPages.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ describe('if there are multiple pages', () => {

describe('if there is page query param in URL', () => {
it('sets this param as the page number', async() => {
useRouter.mockReturnValueOnce({ ...router, query: { page: '3' } });
useRouter.mockReturnValue({ ...router, query: { page: '3' } });

const params: Params<'address_txs'> = {
resourceName: 'address_txs',
Expand Down Expand Up @@ -614,6 +614,56 @@ describe('queries with sorting', () => {
});
});

describe('router query changes', () => {
it('refetches correct page when page number changes in URL', async() => {
const routerPush = jest.fn(() => Promise.resolve());
const router = {
pathname: '/current-route',
push: routerPush,
query: {
page: '3',
next_page_params: encodeURIComponent(JSON.stringify(responses.page_2.next_page_params)),
},
};
useRouter.mockReturnValue(router);

const params: Params<'address_txs'> = {
resourceName: 'address_txs',
pathParams: { hash: addressMock.hash },
};

fetch.once(JSON.stringify(responses.page_3), responseInit);
fetch.once(JSON.stringify(responses.page_2), responseInit);

const { result, rerender } = renderHook(() => useQueryWithPages(params), { wrapper });
await waitForApiResponse();

expect(result.current.data).toEqual(responses.page_3);
expect(result.current.pagination.page).toBe(3);

// Simulate URL change to page 2
useRouter.mockReturnValue({
...router,
query: {
page: '2',
next_page_params: encodeURIComponent(JSON.stringify(responses.page_1.next_page_params)),
},
});

rerender();
await waitForApiResponse();

expect(result.current.data).toEqual(responses.page_2);
expect(result.current.pagination).toMatchObject({
page: 2,
canGoBackwards: false,
hasNextPage: true,
isLoading: false,
isVisible: true,
});
});
});

async function waitForApiResponse() {
await flushPromises();
await act(flushPromises);
Expand Down
20 changes: 19 additions & 1 deletion ui/shared/pagination/useQueryWithPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { animateScroll } from 'react-scroll';

import type { PaginationParams } from './types';

import type { Route } from 'nextjs-routes';

import type { PaginatedResources, PaginationFilters, PaginationSorting, ResourceError, ResourcePayload } from 'lib/api/resources';
import { RESOURCES, SORTING_FIELDS } from 'lib/api/resources';
import type { Params as UseApiQueryParams } from 'lib/api/useApiQuery';
Expand All @@ -26,6 +28,10 @@ type NextPageParams = Record<string, unknown>;

const INITIAL_PAGE_PARAMS = { '1': {} };

function getPageFromQuery(query: Route['query']) {
return query?.page && !Array.isArray(query.page) ? Number(query.page) : 1;
}

function getPaginationParamsFromQuery(queryString: string | Array<string> | undefined) {
if (queryString) {
try {
Expand Down Expand Up @@ -64,7 +70,7 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
const queryClient = useQueryClient();
const router = useRouter();

const [ page, setPage ] = React.useState<number>(router.query.page && !Array.isArray(router.query.page) ? Number(router.query.page) : 1);
const [ page, setPage ] = React.useState<number>(getPageFromQuery(router.query));
const [ pageParams, setPageParams ] = React.useState<Record<number, NextPageParams>>({
[page]: getPaginationParamsFromQuery(router.query.next_page_params),
});
Expand Down Expand Up @@ -221,5 +227,17 @@ export default function useQueryWithPages<Resource extends PaginatedResources>({
}, 0);
}, []);

React.useEffect(() => {
const pageFromQuery = getPageFromQuery(router.query);
const nextPageParamsFromQuery = getPaginationParamsFromQuery(router.query.next_page_params);

setPage(pageFromQuery);
setPageParams(prev => ({
...prev,
[pageFromQuery]: nextPageParamsFromQuery,
}));
setHasPages(pageFromQuery > 1);
}, [ router.query ]);

return { ...queryResult, pagination, onFilterChange, onSortingChange };
}

0 comments on commit 5437124

Please sign in to comment.