From f97b30fe41e7f3c530e1af1c824e90b870c521b2 Mon Sep 17 00:00:00 2001 From: Martin Malfertheiner Date: Fri, 5 Nov 2021 19:58:46 +0100 Subject: [PATCH 1/8] refactoring to support not only search but all kind of query parameters --- src/__test__/inMemoryPagination.test.ts | 35 ++++++----- src/__test__/nextRouterPagination.test.tsx | 63 +++++++++++-------- ...=> reactRouterPagination.testostpesto.tsx} | 16 ++--- src/inMemoryPagination.tsx | 19 +++--- src/nextRouterPagination.tsx | 58 ++++++++++++++--- src/reactRouterPagination.tsx | 4 +- src/types.ts | 13 ++-- 7 files changed, 133 insertions(+), 75 deletions(-) rename src/__test__/{reactRouterPagination.test.tsx => reactRouterPagination.testostpesto.tsx} (85%) diff --git a/src/__test__/inMemoryPagination.test.ts b/src/__test__/inMemoryPagination.test.ts index 6c07d08..2557e46 100644 --- a/src/__test__/inMemoryPagination.test.ts +++ b/src/__test__/inMemoryPagination.test.ts @@ -1,17 +1,16 @@ import { act, renderHook } from '@testing-library/react-hooks' -import { useSearchAndPagination } from '../inMemoryPagination' +import { useQueryAndPagination } from '../inMemoryPagination' import { IndexType } from '../types' test('should initialize pagination', () => { - const { result } = renderHook(() => useSearchAndPagination()) + const { result } = renderHook(() => useQueryAndPagination()) expect(result.current.page).toBe(0) - expect(result.current.search).toBe('') expect(result.current.size).toBe(15) }) test('should change page', () => { - const { result } = renderHook(() => useSearchAndPagination()) + const { result } = renderHook(() => useQueryAndPagination()) act(() => { result.current.actions.setPage(2) @@ -21,17 +20,21 @@ test('should change page', () => { }) test('should change search', () => { - const { result } = renderHook(() => useSearchAndPagination()) + const { result } = renderHook(() => + useQueryAndPagination({ defaultQueryParameters: { query: '' } }) + ) act(() => { - result.current.actions.search('Max') + result.current.actions.query({ query: 'Max' }) }) - expect(result.current.search).toBe('Max') + expect(result.current.queryParameters.query).toBe('Max') }) test('on search change -> page should be reset', () => { - const { result } = renderHook(() => useSearchAndPagination()) + const { result } = renderHook(() => + useQueryAndPagination({ defaultQueryParameters: { query: '' } }) + ) act(() => { result.current.actions.setPage(2) @@ -40,38 +43,40 @@ test('on search change -> page should be reset', () => { expect(result.current.page).toBe(2) act(() => { - result.current.actions.search('Max') + result.current.actions.query({ query: 'Max' }) }) - expect(result.current.search).toBe('Max') + expect(result.current.queryParameters.query).toBe('Max') expect(result.current.page).toBe(0) }) test('clear pagination should reset search and page', () => { - const { result } = renderHook(() => useSearchAndPagination()) + const { result } = renderHook(() => + useQueryAndPagination({ defaultQueryParameters: { query: '' } }) + ) act(() => { - result.current.actions.search('Max') + result.current.actions.query({ query: 'Max' }) }) act(() => { result.current.actions.setPage(2) }) - expect(result.current.search).toBe('Max') + expect(result.current.queryParameters.query).toBe('Max') expect(result.current.page).toBe(2) act(() => { result.current.actions.clear() }) - expect(result.current.search).toBe('') + expect(result.current.queryParameters.query).toBe('') expect(result.current.page).toBe(0) }) test('change default parameters', () => { const { result } = renderHook(() => - useSearchAndPagination({ indexType: IndexType.ONE_BASED, pageSize: 10 }) + useQueryAndPagination({ indexType: IndexType.ONE_BASED, pageSize: 10 }) ) expect(result.current.page).toBe(1) diff --git a/src/__test__/nextRouterPagination.test.tsx b/src/__test__/nextRouterPagination.test.tsx index ff82cd9..0e6c5e2 100644 --- a/src/__test__/nextRouterPagination.test.tsx +++ b/src/__test__/nextRouterPagination.test.tsx @@ -8,11 +8,14 @@ import { IndexType } from '../types' jest.mock('next/router', () => require('next-router-mock')) +beforeEach(() => { + router.query = {} +}) + test('should initialize pagination', () => { const { result } = renderHook(() => useSearchAndPagination()) expect(result.current.page).toBe(0) - expect(result.current.search).toBe('') expect(result.current.size).toBe(15) }) @@ -28,41 +31,25 @@ test('should change page', () => { }) test('should change search', () => { - const { result } = renderHook(() => useSearchAndPagination()) - - act(() => { - result.current.actions.search('Max') - }) - - expect(result.current.search).toBe('Max') - expect(router.query.search).toBe('Max') -}) - -test('on search change -> page should be reset', () => { - const { result } = renderHook(() => useSearchAndPagination()) - - act(() => { - result.current.actions.setPage(2) - }) - - expect(result.current.page).toBe(2) - expect(router.query.page).toBe('2') + const { result } = renderHook(() => + useSearchAndPagination({ defaultQueryParameters: { search: '' } }) + ) act(() => { - result.current.actions.search('Max') + result.current.actions.query({ search: 'Max' }) }) - expect(result.current.search).toBe('Max') - expect(result.current.page).toBe(0) + expect(result.current.queryParameters.search).toBe('Max') expect(router.query.search).toBe('Max') - expect(router.query.page).toBeUndefined() }) test('clear pagination should reset search and page', () => { - const { result } = renderHook(() => useSearchAndPagination()) + const { result } = renderHook(() => + useSearchAndPagination({ defaultQueryParameters: { search: '' } }) + ) act(() => { - result.current.actions.search('Max') + result.current.actions.query({ search: 'Max' }) }) act(() => { @@ -76,7 +63,7 @@ test('clear pagination should reset search and page', () => { result.current.actions.clear() }) - expect(result.current.search).toBe('') + expect(result.current.queryParameters.search).toBe('') expect(result.current.page).toBe(0) expect(router.query.search).toBeUndefined() expect(router.query.page).toBeUndefined() @@ -90,3 +77,25 @@ test('change default parameters', () => { expect(result.current.page).toBe(1) expect(result.current.size).toBe(10) }) + +test('on search change -> page should be reset', () => { + const { result } = renderHook(() => + useSearchAndPagination({ defaultQueryParameters: { search: '' } }) + ) + + act(() => { + result.current.actions.setPage(2) + }) + + expect(result.current.page).toBe(2) + expect(router.query.page).toBe('2') + + act(() => { + result.current.actions.query({ search: 'Max' }) + }) + + expect(result.current.queryParameters.search).toBe('Max') + expect(result.current.page).toBe(0) + expect(router.query.search).toBe('Max') + expect(router.query.page).toBeUndefined() +}) diff --git a/src/__test__/reactRouterPagination.test.tsx b/src/__test__/reactRouterPagination.testostpesto.tsx similarity index 85% rename from src/__test__/reactRouterPagination.test.tsx rename to src/__test__/reactRouterPagination.testostpesto.tsx index 9be8fff..222097a 100644 --- a/src/__test__/reactRouterPagination.test.tsx +++ b/src/__test__/reactRouterPagination.testostpesto.tsx @@ -10,7 +10,7 @@ test('should initialize pagination', () => { const { result } = renderHook(() => useSearchAndPagination(), { wrapper }) expect(result.current.page).toBe(0) - expect(result.current.search).toBe('') + expect(result.current.query).toBe('') expect(result.current.size).toBe(15) }) @@ -29,10 +29,10 @@ test('should change search', () => { const { result } = renderHook(() => useSearchAndPagination(), { wrapper }) act(() => { - result.current.actions.search('Max') + result.current.actions.query('Max') }) - expect(result.current.search).toBe('Max') + expect(result.current.query).toBe('Max') expect(window.location.search).toBe('?search=Max') }) @@ -46,10 +46,10 @@ test('on search change -> page should be reset', () => { expect(result.current.page).toBe(2) act(() => { - result.current.actions.search('Max') + result.current.actions.query('Max') }) - expect(result.current.search).toBe('Max') + expect(result.current.query).toBe('Max') expect(result.current.page).toBe(0) expect(window.location.search).toBe('?search=Max') }) @@ -58,21 +58,21 @@ test('clear pagination should reset search and page', () => { const { result } = renderHook(() => useSearchAndPagination(), { wrapper }) act(() => { - result.current.actions.search('Max') + result.current.actions.query('Max') }) act(() => { result.current.actions.setPage(2) }) - expect(result.current.search).toBe('Max') + expect(result.current.query).toBe('Max') expect(result.current.page).toBe(2) act(() => { result.current.actions.clear() }) - expect(result.current.search).toBe('') + expect(result.current.query).toBe('') expect(result.current.page).toBe(0) expect(window.location.search).toBe('') }) diff --git a/src/inMemoryPagination.tsx b/src/inMemoryPagination.tsx index 5a9f1df..be32a43 100644 --- a/src/inMemoryPagination.tsx +++ b/src/inMemoryPagination.tsx @@ -1,28 +1,29 @@ import { useCallback, useMemo, useState } from 'react' -import { IndexType, IUseSearchAndPagination } from './types' +import { IndexType, IUseQueryAndPagination, QueryParameters } from './types' -export const useSearchAndPagination: IUseSearchAndPagination = function ( - config -) { +export const useQueryAndPagination: IUseQueryAndPagination = function (config) { const { indexType = IndexType.ZERO_BASED, pageSize = 15 } = config || {} const firstPage = indexType === IndexType.ZERO_BASED ? 0 : 1 const initialState = useMemo( () => ({ page: firstPage, size: pageSize, - searchQuery: '', + queryParameters: config?.defaultQueryParameters || {}, }), [] ) const [state, setState] = useState(initialState) - const search = useCallback((query: string) => { + const query = useCallback((queryParameters: QueryParameters) => { setState((currentState) => { return { ...currentState, page: 0, - searchQuery: query, + queryParameters: { + ...currentState.queryParameters, + ...queryParameters, + }, } }) }, []) @@ -43,9 +44,9 @@ export const useSearchAndPagination: IUseSearchAndPagination = function ( }, []) return { - search: state.searchQuery, + queryParameters: state.queryParameters, actions: { - search, + query, clear, setPage, }, diff --git a/src/nextRouterPagination.tsx b/src/nextRouterPagination.tsx index 67e8a71..3757f7a 100644 --- a/src/nextRouterPagination.tsx +++ b/src/nextRouterPagination.tsx @@ -1,7 +1,8 @@ +import { ParsedUrlQuery } from 'querystring' import { useRouter } from 'next/router' import { useCallback } from 'react' -import { IndexType, IUseSearchAndPagination } from './types' +import { IndexType, IUseQueryAndPagination, QueryParameters } from './types' import { convert } from './utils' function getSingleParameterValue( @@ -10,7 +11,29 @@ function getSingleParameterValue( return Array.isArray(parameter) ? parameter[0] : parameter } -export const useSearchAndPagination: IUseSearchAndPagination = function ( +function extractCurrentQueryParameters( + query: ParsedUrlQuery, + defaultQueryParameters?: QueryParameters +) { + if (!defaultQueryParameters) { + return {} + } + + const result: QueryParameters = defaultQueryParameters + + for (const parameter in defaultQueryParameters) { + if ( + query[parameter] && + getSingleParameterValue(query[parameter]) !== undefined + ) { + result[parameter] = getSingleParameterValue(query[parameter]) as string + } + } + + return result +} + +export const useSearchAndPagination: IUseQueryAndPagination = function ( config ) { const { indexType = IndexType.ZERO_BASED, pageSize = 15 } = config || {} @@ -30,11 +53,22 @@ export const useSearchAndPagination: IUseSearchAndPagination = function ( [router] ) - const search = useCallback( - (query: string) => { - const params: { page?: string; size?: string; search?: string } = { + const query = useCallback( + (queryParameters: QueryParameters) => { + const params = { ...router.query, - search: query === '' ? undefined : query, + } + + for (const parameter in queryParameters) { + if ( + config?.defaultQueryParameters && + config.defaultQueryParameters[parameter] === + queryParameters[parameter] + ) { + delete params[parameter] + } else { + params[parameter] = queryParameters[parameter].toString() + } } delete params['page'] @@ -52,24 +86,30 @@ export const useSearchAndPagination: IUseSearchAndPagination = function ( ...router.query, } - delete params['search'] delete params['page'] delete params['size'] + for (const parameter in config?.defaultQueryParameters) { + delete params[parameter] + } + router.push({ query: params, }) }, [router]) return { - search: getSingleParameterValue(router.query.search) || '', + queryParameters: extractCurrentQueryParameters( + router.query, + config?.defaultQueryParameters + ), page: convert( getSingleParameterValue(router.query.page) || null, indexType === IndexType.ZERO_BASED ? 0 : 1 ), size: convert(getSingleParameterValue(router.query.size) || null, pageSize), actions: { - search, + query, clear, setPage, }, diff --git a/src/reactRouterPagination.tsx b/src/reactRouterPagination.tsx index 4db2572..ae7df04 100644 --- a/src/reactRouterPagination.tsx +++ b/src/reactRouterPagination.tsx @@ -1,10 +1,10 @@ import { useCallback, useMemo } from 'react' import { useHistory, useLocation, useRouteMatch } from 'react-router-dom' -import { IndexType, IUseSearchAndPagination } from './types' +import { IndexType, IUseQueryAndPagination } from './types' import { convert } from './utils' -export const useSearchAndPagination: IUseSearchAndPagination = function ( +export const useSearchAndPagination: IUseQueryAndPagination = function ( config ) { const { indexType = IndexType.ZERO_BASED, pageSize = 15 } = config || {} diff --git a/src/types.ts b/src/types.ts index 4a0efcf..dcc080c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,24 +3,27 @@ export enum IndexType { ONE_BASED = 1, } +export type QueryParameters = Record + export type Config = { indexType?: IndexType pageSize?: number + defaultQueryParameters?: QueryParameters } export type Actions = { - search: (query: string) => void + query: (query: QueryParameters) => void clear: () => void setPage: (page: number) => void } -export type UseSearchAndPagination = { - search: string +export type UseQueryAndPagination = { + queryParameters: QueryParameters page: number size: number actions: Actions } -export interface IUseSearchAndPagination { - (config?: Config): UseSearchAndPagination +export interface IUseQueryAndPagination { + (config?: Config): UseQueryAndPagination } From bcea13431df3dadba1910f4d3ec83ed46fcb4c27 Mon Sep 17 00:00:00 2001 From: Martin Malfertheiner Date: Mon, 8 Nov 2021 08:23:50 +0100 Subject: [PATCH 2/8] refactoring react-router implementation to new interface --- src/__test__/nextRouterPagination.test.tsx | 14 ++--- ...sto.tsx => reactRouterPagination.test.tsx} | 54 ++++++++----------- src/nextRouterPagination.tsx | 4 +- src/reactRouterPagination.tsx | 54 ++++++++++++++----- 4 files changed, 73 insertions(+), 53 deletions(-) rename src/__test__/{reactRouterPagination.testostpesto.tsx => reactRouterPagination.test.tsx} (51%) diff --git a/src/__test__/nextRouterPagination.test.tsx b/src/__test__/nextRouterPagination.test.tsx index 0e6c5e2..0a7a4b8 100644 --- a/src/__test__/nextRouterPagination.test.tsx +++ b/src/__test__/nextRouterPagination.test.tsx @@ -3,7 +3,7 @@ import React from 'react' import { act, renderHook } from '@testing-library/react-hooks' import router from 'next/router' -import { useSearchAndPagination } from '../nextRouterPagination' +import { useQueryAndPagination } from '../nextRouterPagination' import { IndexType } from '../types' jest.mock('next/router', () => require('next-router-mock')) @@ -13,14 +13,14 @@ beforeEach(() => { }) test('should initialize pagination', () => { - const { result } = renderHook(() => useSearchAndPagination()) + const { result } = renderHook(() => useQueryAndPagination()) expect(result.current.page).toBe(0) expect(result.current.size).toBe(15) }) test('should change page', () => { - const { result } = renderHook(() => useSearchAndPagination()) + const { result } = renderHook(() => useQueryAndPagination()) act(() => { result.current.actions.setPage(2) @@ -32,7 +32,7 @@ test('should change page', () => { test('should change search', () => { const { result } = renderHook(() => - useSearchAndPagination({ defaultQueryParameters: { search: '' } }) + useQueryAndPagination({ defaultQueryParameters: { search: '' } }) ) act(() => { @@ -45,7 +45,7 @@ test('should change search', () => { test('clear pagination should reset search and page', () => { const { result } = renderHook(() => - useSearchAndPagination({ defaultQueryParameters: { search: '' } }) + useQueryAndPagination({ defaultQueryParameters: { search: '' } }) ) act(() => { @@ -71,7 +71,7 @@ test('clear pagination should reset search and page', () => { test('change default parameters', () => { const { result } = renderHook(() => - useSearchAndPagination({ indexType: IndexType.ONE_BASED, pageSize: 10 }) + useQueryAndPagination({ indexType: IndexType.ONE_BASED, pageSize: 10 }) ) expect(result.current.page).toBe(1) @@ -80,7 +80,7 @@ test('change default parameters', () => { test('on search change -> page should be reset', () => { const { result } = renderHook(() => - useSearchAndPagination({ defaultQueryParameters: { search: '' } }) + useQueryAndPagination({ defaultQueryParameters: { search: '' } }) ) act(() => { diff --git a/src/__test__/reactRouterPagination.testostpesto.tsx b/src/__test__/reactRouterPagination.test.tsx similarity index 51% rename from src/__test__/reactRouterPagination.testostpesto.tsx rename to src/__test__/reactRouterPagination.test.tsx index 222097a..917db21 100644 --- a/src/__test__/reactRouterPagination.testostpesto.tsx +++ b/src/__test__/reactRouterPagination.test.tsx @@ -1,21 +1,23 @@ import React from 'react' import { act, renderHook } from '@testing-library/react-hooks' import { BrowserRouter as Router } from 'react-router-dom' -import { useSearchAndPagination } from '../reactRouterPagination' +import { useQueryAndPagination } from '../reactRouterPagination' import { IndexType } from '../types' - const wrapper: React.FC = ({ children }) => {children} +beforeEach(() => { + window.history.pushState({}, '', '/') +}) + test('should initialize pagination', () => { - const { result } = renderHook(() => useSearchAndPagination(), { wrapper }) + const { result } = renderHook(() => useQueryAndPagination(), { wrapper }) expect(result.current.page).toBe(0) - expect(result.current.query).toBe('') expect(result.current.size).toBe(15) }) test('should change page', () => { - const { result } = renderHook(() => useSearchAndPagination(), { wrapper }) + const { result } = renderHook(() => useQueryAndPagination(), { wrapper }) act(() => { result.current.actions.setPage(2) @@ -26,53 +28,43 @@ test('should change page', () => { }) test('should change search', () => { - const { result } = renderHook(() => useSearchAndPagination(), { wrapper }) - - act(() => { - result.current.actions.query('Max') - }) - - expect(result.current.query).toBe('Max') - expect(window.location.search).toBe('?search=Max') -}) - -test('on search change -> page should be reset', () => { - const { result } = renderHook(() => useSearchAndPagination(), { wrapper }) - - act(() => { - result.current.actions.setPage(2) - }) - - expect(result.current.page).toBe(2) + const { result } = renderHook( + () => useQueryAndPagination({ defaultQueryParameters: { search: '' } }), + { wrapper } + ) act(() => { - result.current.actions.query('Max') + result.current.actions.query({ search: 'Max' }) }) - expect(result.current.query).toBe('Max') - expect(result.current.page).toBe(0) + expect(result.current.queryParameters.search).toBe('Max') expect(window.location.search).toBe('?search=Max') }) test('clear pagination should reset search and page', () => { - const { result } = renderHook(() => useSearchAndPagination(), { wrapper }) + const { result } = renderHook( + () => useQueryAndPagination({ defaultQueryParameters: { search: '' } }), + { wrapper } + ) + + console.log(window.location.search) act(() => { - result.current.actions.query('Max') + result.current.actions.query({ search: 'Max' }) }) act(() => { result.current.actions.setPage(2) }) - expect(result.current.query).toBe('Max') + expect(result.current.queryParameters.search).toBe('Max') expect(result.current.page).toBe(2) act(() => { result.current.actions.clear() }) - expect(result.current.query).toBe('') + expect(result.current.queryParameters.search).toBe('') expect(result.current.page).toBe(0) expect(window.location.search).toBe('') }) @@ -80,7 +72,7 @@ test('clear pagination should reset search and page', () => { test('change default parameters', () => { const { result } = renderHook( () => - useSearchAndPagination({ indexType: IndexType.ONE_BASED, pageSize: 10 }), + useQueryAndPagination({ indexType: IndexType.ONE_BASED, pageSize: 10 }), { wrapper } ) diff --git a/src/nextRouterPagination.tsx b/src/nextRouterPagination.tsx index 3757f7a..1d0641c 100644 --- a/src/nextRouterPagination.tsx +++ b/src/nextRouterPagination.tsx @@ -33,9 +33,7 @@ function extractCurrentQueryParameters( return result } -export const useSearchAndPagination: IUseQueryAndPagination = function ( - config -) { +export const useQueryAndPagination: IUseQueryAndPagination = function (config) { const { indexType = IndexType.ZERO_BASED, pageSize = 15 } = config || {} const router = useRouter() diff --git a/src/reactRouterPagination.tsx b/src/reactRouterPagination.tsx index ae7df04..86558ac 100644 --- a/src/reactRouterPagination.tsx +++ b/src/reactRouterPagination.tsx @@ -1,12 +1,29 @@ import { useCallback, useMemo } from 'react' import { useHistory, useLocation, useRouteMatch } from 'react-router-dom' -import { IndexType, IUseQueryAndPagination } from './types' +import { IndexType, IUseQueryAndPagination, QueryParameters } from './types' import { convert } from './utils' -export const useSearchAndPagination: IUseQueryAndPagination = function ( - config +function extractCurrentQueryParameters( + query: URLSearchParams, + defaultQueryParameters?: QueryParameters ) { + if (!defaultQueryParameters) { + return {} + } + + const result: QueryParameters = defaultQueryParameters + + for (const parameter in defaultQueryParameters) { + if (query.get(parameter)) { + result[parameter] = query.get(parameter) as string + } + } + + return result +} + +export const useQueryAndPagination: IUseQueryAndPagination = function (config) { const { indexType = IndexType.ZERO_BASED, pageSize = 15 } = config || {} const routerHistory = useHistory() const { url: routerUrl } = useRouteMatch() @@ -14,13 +31,20 @@ export const useSearchAndPagination: IUseQueryAndPagination = function ( const params = useMemo(() => new URLSearchParams(routeQuery), [routeQuery]) - const search = useCallback( - (query: string) => { - if (query === '') { - params.delete('search') - } else { - params.set('search', query) + const query = useCallback( + (queryParameters: QueryParameters) => { + for (const parameter in queryParameters) { + if ( + config?.defaultQueryParameters && + config.defaultQueryParameters[parameter] === + queryParameters[parameter] + ) { + params.delete(parameter) + } else { + params.set(parameter, queryParameters[parameter].toString()) + } } + params.delete('page') params.delete('size') @@ -33,7 +57,10 @@ export const useSearchAndPagination: IUseQueryAndPagination = function ( ) const clear = useCallback(() => { - params.delete('search') + for (const parameter in config?.defaultQueryParameters) { + params.delete(parameter) + } + params.delete('page') params.delete('size') @@ -55,14 +82,17 @@ export const useSearchAndPagination: IUseQueryAndPagination = function ( ) return { - search: params.get('search') || '', + queryParameters: extractCurrentQueryParameters( + params, + config?.defaultQueryParameters + ), page: convert( params.get('page'), indexType === IndexType.ZERO_BASED ? 0 : 1 ), size: convert(params.get('size'), pageSize), actions: { - search, + query, clear, setPage, }, From d6029a1c4ee45c86e6db6efb5279c0bde0804600 Mon Sep 17 00:00:00 2001 From: Martin Malfertheiner Date: Mon, 8 Nov 2021 10:12:18 +0100 Subject: [PATCH 3/8] add more tests to router implementations --- src/__test__/inMemoryPagination.test.ts | 33 +++++++++ src/__test__/nextRouterPagination.test.tsx | 66 ++++++++++++++++++ src/__test__/reactRouterPagination.test.tsx | 76 ++++++++++++++++++++- src/nextRouterPagination.tsx | 2 +- src/reactRouterPagination.tsx | 2 +- 5 files changed, 175 insertions(+), 4 deletions(-) diff --git a/src/__test__/inMemoryPagination.test.ts b/src/__test__/inMemoryPagination.test.ts index 2557e46..5805f33 100644 --- a/src/__test__/inMemoryPagination.test.ts +++ b/src/__test__/inMemoryPagination.test.ts @@ -82,3 +82,36 @@ test('change default parameters', () => { expect(result.current.page).toBe(1) expect(result.current.size).toBe(10) }) + +test('query multiple different properties, should keep them all', () => { + const { result } = renderHook(() => + useQueryAndPagination({ + defaultQueryParameters: { query: '', department: '' }, + }) + ) + + act(() => { + result.current.actions.query({ query: 'Max' }) + result.current.actions.query({ department: 'IT' }) + }) + + expect(result.current.queryParameters.query).toBe('Max') + expect(result.current.queryParameters.department).toBe('IT') +}) + +test('query a property that is not configured, should do nothing', () => { + const { result } = renderHook(() => + useQueryAndPagination({ + defaultQueryParameters: { query: '' }, + }) + ) + + act(() => { + result.current.actions.query({ department: 'IT' }) + }) + + expect(result.current.queryParameters.query).toBe('') + expect(result.current.queryParameters.department).toBeUndefined() +}) + +// test('properties in the URL, that are not part of the configuration should be left untouched', () => {}) diff --git a/src/__test__/nextRouterPagination.test.tsx b/src/__test__/nextRouterPagination.test.tsx index 0a7a4b8..fd04e9d 100644 --- a/src/__test__/nextRouterPagination.test.tsx +++ b/src/__test__/nextRouterPagination.test.tsx @@ -99,3 +99,69 @@ test('on search change -> page should be reset', () => { expect(router.query.search).toBe('Max') expect(router.query.page).toBeUndefined() }) + +test('query multiple different properties, should keep them all', () => { + const { result } = renderHook(() => + useQueryAndPagination({ + defaultQueryParameters: { search: '', department: '' }, + }) + ) + + act(() => { + result.current.actions.query({ search: 'Max' }) + result.current.actions.query({ department: 'IT' }) + }) + + expect(result.current.queryParameters.search).toBe('Max') + expect(result.current.queryParameters.department).toBe('IT') +}) + +test('query a property that is not configured, should do nothing', () => { + const { result } = renderHook(() => + useQueryAndPagination({ + defaultQueryParameters: { search: '' }, + }) + ) + + act(() => { + result.current.actions.query({ department: 'IT' }) + }) + + expect(result.current.queryParameters.search).toBe('') + expect(result.current.queryParameters.department).toBeUndefined() +}) + +test('properties in the URL, that are not part of the configuration should be left untouched', () => { + router.query = { greeting: 'hello' } + + const { result } = renderHook(() => + useQueryAndPagination({ + defaultQueryParameters: { search: '' }, + }) + ) + + act(() => { + result.current.actions.query({ search: 'Max' }) + }) + + expect(result.current.queryParameters.search).toBe('Max') + expect(result.current.queryParameters.greeting).toBeUndefined() + expect(router.query.greeting).toBe('hello') +}) + +test('query property with default value, should remove it from url', () => { + router.query = { search: 'Max' } + + const { result } = renderHook(() => + useQueryAndPagination({ + defaultQueryParameters: { search: '' }, + }) + ) + + act(() => { + result.current.actions.query({ search: '' }) + }) + + expect(result.current.queryParameters.search).toBe('') + expect(router.query.search).toBeUndefined() +}) diff --git a/src/__test__/reactRouterPagination.test.tsx b/src/__test__/reactRouterPagination.test.tsx index 917db21..f46c2cd 100644 --- a/src/__test__/reactRouterPagination.test.tsx +++ b/src/__test__/reactRouterPagination.test.tsx @@ -47,8 +47,6 @@ test('clear pagination should reset search and page', () => { { wrapper } ) - console.log(window.location.search) - act(() => { result.current.actions.query({ search: 'Max' }) }) @@ -79,3 +77,77 @@ test('change default parameters', () => { expect(result.current.page).toBe(1) expect(result.current.size).toBe(10) }) + +test('query multiple different properties, should keep them all', () => { + const { result } = renderHook( + () => + useQueryAndPagination({ + defaultQueryParameters: { search: '', department: '' }, + }), + { wrapper } + ) + + act(() => { + result.current.actions.query({ search: 'Max' }) + result.current.actions.query({ department: 'IT' }) + }) + + expect(result.current.queryParameters.search).toBe('Max') + expect(result.current.queryParameters.department).toBe('IT') +}) + +test('query a property that is not configured, should do nothing', () => { + const { result } = renderHook( + () => + useQueryAndPagination({ + defaultQueryParameters: { search: '' }, + }), + { wrapper } + ) + + act(() => { + result.current.actions.query({ department: 'IT' }) + }) + + expect(result.current.queryParameters.search).toBe('') + expect(result.current.queryParameters.department).toBeUndefined() +}) + +test('properties in the URL, that are not part of the configuration should be left untouched', () => { + window.history.pushState({}, '', '/?greeting=hello') + + const { result } = renderHook( + () => + useQueryAndPagination({ + defaultQueryParameters: { search: '' }, + }), + { wrapper } + ) + + act(() => { + result.current.actions.query({ search: 'Max' }) + }) + + expect(result.current.queryParameters.search).toBe('Max') + expect(result.current.queryParameters.greeting).toBeUndefined() + expect(window.location.search).toBe('?greeting=hello&search=Max') +}) + +test('query property with default value, should remove it from url', () => { + window.history.pushState({}, '', '/?search=Anton') + + const { result } = renderHook( + () => + useQueryAndPagination({ + defaultQueryParameters: { search: '' }, + }), + { wrapper } + ) + + act(() => { + result.current.actions.query({ search: '' }) + }) + + expect(result.current.queryParameters.search).toBe('') + expect(window.location.search).toBe('') +}) diff --git a/src/nextRouterPagination.tsx b/src/nextRouterPagination.tsx index 1d0641c..fe695dc 100644 --- a/src/nextRouterPagination.tsx +++ b/src/nextRouterPagination.tsx @@ -19,7 +19,7 @@ function extractCurrentQueryParameters( return {} } - const result: QueryParameters = defaultQueryParameters + const result: QueryParameters = { ...defaultQueryParameters } for (const parameter in defaultQueryParameters) { if ( diff --git a/src/reactRouterPagination.tsx b/src/reactRouterPagination.tsx index 86558ac..f905e25 100644 --- a/src/reactRouterPagination.tsx +++ b/src/reactRouterPagination.tsx @@ -12,7 +12,7 @@ function extractCurrentQueryParameters( return {} } - const result: QueryParameters = defaultQueryParameters + const result: QueryParameters = { ...defaultQueryParameters } for (const parameter in defaultQueryParameters) { if (query.get(parameter)) { From 8c248d857804484fc53402cf93171cb76569e5fe Mon Sep 17 00:00:00 2001 From: Martin Malfertheiner Date: Mon, 8 Nov 2021 10:28:13 +0100 Subject: [PATCH 4/8] an unkown query property should not be saved in state --- src/__test__/inMemoryPagination.test.ts | 32 ++++++++++++------------- src/inMemoryPagination.tsx | 21 ++++++++++++---- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/__test__/inMemoryPagination.test.ts b/src/__test__/inMemoryPagination.test.ts index 5805f33..0fa6479 100644 --- a/src/__test__/inMemoryPagination.test.ts +++ b/src/__test__/inMemoryPagination.test.ts @@ -21,19 +21,19 @@ test('should change page', () => { test('should change search', () => { const { result } = renderHook(() => - useQueryAndPagination({ defaultQueryParameters: { query: '' } }) + useQueryAndPagination({ defaultQueryParameters: { search: '' } }) ) act(() => { - result.current.actions.query({ query: 'Max' }) + result.current.actions.query({ search: 'Max' }) }) - expect(result.current.queryParameters.query).toBe('Max') + expect(result.current.queryParameters.search).toBe('Max') }) test('on search change -> page should be reset', () => { const { result } = renderHook(() => - useQueryAndPagination({ defaultQueryParameters: { query: '' } }) + useQueryAndPagination({ defaultQueryParameters: { search: '' } }) ) act(() => { @@ -43,34 +43,34 @@ test('on search change -> page should be reset', () => { expect(result.current.page).toBe(2) act(() => { - result.current.actions.query({ query: 'Max' }) + result.current.actions.query({ search: 'Max' }) }) - expect(result.current.queryParameters.query).toBe('Max') + expect(result.current.queryParameters.search).toBe('Max') expect(result.current.page).toBe(0) }) test('clear pagination should reset search and page', () => { const { result } = renderHook(() => - useQueryAndPagination({ defaultQueryParameters: { query: '' } }) + useQueryAndPagination({ defaultQueryParameters: { search: '' } }) ) act(() => { - result.current.actions.query({ query: 'Max' }) + result.current.actions.query({ search: 'Max' }) }) act(() => { result.current.actions.setPage(2) }) - expect(result.current.queryParameters.query).toBe('Max') + expect(result.current.queryParameters.search).toBe('Max') expect(result.current.page).toBe(2) act(() => { result.current.actions.clear() }) - expect(result.current.queryParameters.query).toBe('') + expect(result.current.queryParameters.search).toBe('') expect(result.current.page).toBe(0) }) @@ -86,23 +86,23 @@ test('change default parameters', () => { test('query multiple different properties, should keep them all', () => { const { result } = renderHook(() => useQueryAndPagination({ - defaultQueryParameters: { query: '', department: '' }, + defaultQueryParameters: { search: '', department: '' }, }) ) act(() => { - result.current.actions.query({ query: 'Max' }) + result.current.actions.query({ search: 'Max' }) result.current.actions.query({ department: 'IT' }) }) - expect(result.current.queryParameters.query).toBe('Max') + expect(result.current.queryParameters.search).toBe('Max') expect(result.current.queryParameters.department).toBe('IT') }) test('query a property that is not configured, should do nothing', () => { const { result } = renderHook(() => useQueryAndPagination({ - defaultQueryParameters: { query: '' }, + defaultQueryParameters: { search: '' }, }) ) @@ -110,8 +110,6 @@ test('query a property that is not configured, should do nothing', () => { result.current.actions.query({ department: 'IT' }) }) - expect(result.current.queryParameters.query).toBe('') + expect(result.current.queryParameters.search).toBe('') expect(result.current.queryParameters.department).toBeUndefined() }) - -// test('properties in the URL, that are not part of the configuration should be left untouched', () => {}) diff --git a/src/inMemoryPagination.tsx b/src/inMemoryPagination.tsx index be32a43..22bc1c6 100644 --- a/src/inMemoryPagination.tsx +++ b/src/inMemoryPagination.tsx @@ -17,13 +17,26 @@ export const useQueryAndPagination: IUseQueryAndPagination = function (config) { const query = useCallback((queryParameters: QueryParameters) => { setState((currentState) => { + const updatedQueryParameters = { + ...currentState.queryParameters, + ...queryParameters, + } + + for (const parameter in queryParameters) { + if ( + !!config?.defaultQueryParameters && + (config.defaultQueryParameters[parameter] === undefined || + config.defaultQueryParameters[parameter] === + queryParameters[parameter]) + ) { + delete updatedQueryParameters[parameter] + } + } + return { ...currentState, page: 0, - queryParameters: { - ...currentState.queryParameters, - ...queryParameters, - }, + queryParameters: updatedQueryParameters, } }) }, []) From 4e7494bddaff90c537dc8082ea60947cb19d6a23 Mon Sep 17 00:00:00 2001 From: Martin Malfertheiner Date: Mon, 8 Nov 2021 11:30:05 +0100 Subject: [PATCH 5/8] rename action to be more precise --- package.json | 2 +- src/__test__/inMemoryPagination.test.ts | 12 ++++++------ src/__test__/nextRouterPagination.test.tsx | 16 ++++++++-------- src/__test__/reactRouterPagination.test.tsx | 14 +++++++------- src/inMemoryPagination.tsx | 4 ++-- src/nextRouterPagination.tsx | 4 ++-- src/reactRouterPagination.tsx | 4 ++-- src/types.ts | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index e2ac2ef..b32022e 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "eslint-plugin-prettier": "^3.3.1", "jest": "^26.6.3", "next": "^11.0.1", - "next-router-mock": "^0.1.4", + "next-router-mock": "^0.6.1", "prettier": "^2.2.1", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/src/__test__/inMemoryPagination.test.ts b/src/__test__/inMemoryPagination.test.ts index 0fa6479..992dba2 100644 --- a/src/__test__/inMemoryPagination.test.ts +++ b/src/__test__/inMemoryPagination.test.ts @@ -25,7 +25,7 @@ test('should change search', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -43,7 +43,7 @@ test('on search change -> page should be reset', () => { expect(result.current.page).toBe(2) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -56,7 +56,7 @@ test('clear pagination should reset search and page', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) act(() => { @@ -91,8 +91,8 @@ test('query multiple different properties, should keep them all', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) - result.current.actions.query({ department: 'IT' }) + result.current.actions.updateQuery({ search: 'Max' }) + result.current.actions.updateQuery({ department: 'IT' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -107,7 +107,7 @@ test('query a property that is not configured, should do nothing', () => { ) act(() => { - result.current.actions.query({ department: 'IT' }) + result.current.actions.updateQuery({ department: 'IT' }) }) expect(result.current.queryParameters.search).toBe('') diff --git a/src/__test__/nextRouterPagination.test.tsx b/src/__test__/nextRouterPagination.test.tsx index fd04e9d..9c09db2 100644 --- a/src/__test__/nextRouterPagination.test.tsx +++ b/src/__test__/nextRouterPagination.test.tsx @@ -36,7 +36,7 @@ test('should change search', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -49,7 +49,7 @@ test('clear pagination should reset search and page', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) act(() => { @@ -91,7 +91,7 @@ test('on search change -> page should be reset', () => { expect(router.query.page).toBe('2') act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -108,8 +108,8 @@ test('query multiple different properties, should keep them all', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) - result.current.actions.query({ department: 'IT' }) + result.current.actions.updateQuery({ search: 'Max' }) + result.current.actions.updateQuery({ department: 'IT' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -124,7 +124,7 @@ test('query a property that is not configured, should do nothing', () => { ) act(() => { - result.current.actions.query({ department: 'IT' }) + result.current.actions.updateQuery({ department: 'IT' }) }) expect(result.current.queryParameters.search).toBe('') @@ -141,7 +141,7 @@ test('properties in the URL, that are not part of the configuration should be le ) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -159,7 +159,7 @@ test('query property with default value, should remove it from url', () => { ) act(() => { - result.current.actions.query({ search: '' }) + result.current.actions.updateQuery({ search: '' }) }) expect(result.current.queryParameters.search).toBe('') diff --git a/src/__test__/reactRouterPagination.test.tsx b/src/__test__/reactRouterPagination.test.tsx index f46c2cd..c296785 100644 --- a/src/__test__/reactRouterPagination.test.tsx +++ b/src/__test__/reactRouterPagination.test.tsx @@ -34,7 +34,7 @@ test('should change search', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -48,7 +48,7 @@ test('clear pagination should reset search and page', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) act(() => { @@ -88,8 +88,8 @@ test('query multiple different properties, should keep them all', () => { ) act(() => { - result.current.actions.query({ search: 'Max' }) - result.current.actions.query({ department: 'IT' }) + result.current.actions.updateQuery({ search: 'Max' }) + result.current.actions.updateQuery({ department: 'IT' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -106,7 +106,7 @@ test('query a property that is not configured, should do nothing', () => { ) act(() => { - result.current.actions.query({ department: 'IT' }) + result.current.actions.updateQuery({ department: 'IT' }) }) expect(result.current.queryParameters.search).toBe('') @@ -125,7 +125,7 @@ test('properties in the URL, that are not part of the configuration should be le ) act(() => { - result.current.actions.query({ search: 'Max' }) + result.current.actions.updateQuery({ search: 'Max' }) }) expect(result.current.queryParameters.search).toBe('Max') @@ -145,7 +145,7 @@ test('query property with default value, should remove it from url', () => { ) act(() => { - result.current.actions.query({ search: '' }) + result.current.actions.updateQuery({ search: '' }) }) expect(result.current.queryParameters.search).toBe('') diff --git a/src/inMemoryPagination.tsx b/src/inMemoryPagination.tsx index 22bc1c6..9c26f77 100644 --- a/src/inMemoryPagination.tsx +++ b/src/inMemoryPagination.tsx @@ -15,7 +15,7 @@ export const useQueryAndPagination: IUseQueryAndPagination = function (config) { const [state, setState] = useState(initialState) - const query = useCallback((queryParameters: QueryParameters) => { + const updateQuery = useCallback((queryParameters: QueryParameters) => { setState((currentState) => { const updatedQueryParameters = { ...currentState.queryParameters, @@ -59,7 +59,7 @@ export const useQueryAndPagination: IUseQueryAndPagination = function (config) { return { queryParameters: state.queryParameters, actions: { - query, + updateQuery, clear, setPage, }, diff --git a/src/nextRouterPagination.tsx b/src/nextRouterPagination.tsx index fe695dc..744826a 100644 --- a/src/nextRouterPagination.tsx +++ b/src/nextRouterPagination.tsx @@ -51,7 +51,7 @@ export const useQueryAndPagination: IUseQueryAndPagination = function (config) { [router] ) - const query = useCallback( + const updateQuery = useCallback( (queryParameters: QueryParameters) => { const params = { ...router.query, @@ -107,7 +107,7 @@ export const useQueryAndPagination: IUseQueryAndPagination = function (config) { ), size: convert(getSingleParameterValue(router.query.size) || null, pageSize), actions: { - query, + updateQuery, clear, setPage, }, diff --git a/src/reactRouterPagination.tsx b/src/reactRouterPagination.tsx index f905e25..6b43520 100644 --- a/src/reactRouterPagination.tsx +++ b/src/reactRouterPagination.tsx @@ -31,7 +31,7 @@ export const useQueryAndPagination: IUseQueryAndPagination = function (config) { const params = useMemo(() => new URLSearchParams(routeQuery), [routeQuery]) - const query = useCallback( + const updateQuery = useCallback( (queryParameters: QueryParameters) => { for (const parameter in queryParameters) { if ( @@ -92,7 +92,7 @@ export const useQueryAndPagination: IUseQueryAndPagination = function (config) { ), size: convert(params.get('size'), pageSize), actions: { - query, + updateQuery, clear, setPage, }, diff --git a/src/types.ts b/src/types.ts index dcc080c..109ec7d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -12,7 +12,7 @@ export type Config = { } export type Actions = { - query: (query: QueryParameters) => void + updateQuery: (query: QueryParameters) => void clear: () => void setPage: (page: number) => void } From 8d40b88f182f1b9620a006a35c7b480648f03e8e Mon Sep 17 00:00:00 2001 From: Martin Malfertheiner Date: Mon, 8 Nov 2021 11:34:51 +0100 Subject: [PATCH 6/8] skipLibCheck as Next won't build otherwise --- tsconfig.esnext.json | 3 ++- tsconfig.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tsconfig.esnext.json b/tsconfig.esnext.json index b1898a6..074e202 100644 --- a/tsconfig.esnext.json +++ b/tsconfig.esnext.json @@ -9,7 +9,8 @@ "outDir": "./dist/esm", "declaration": true, "strict": true, + "skipLibCheck": true }, "include": ["src"], "exclude": ["node_modules", "**/__test__/*", "**/__tests__/*"] -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index 4eba278..fc22be6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,8 @@ "outDir": "./dist", "declaration": true, "strict": true, - "sourceMap": true + "sourceMap": true, + "skipLibCheck": true }, "include": ["src"], "exclude": ["node_modules", "**/__test__/*", "**/__tests__/*"] From 5c78ef10908a207734a25a9e2557483d42e767b0 Mon Sep 17 00:00:00 2001 From: Martin Malfertheiner Date: Mon, 8 Nov 2021 11:41:18 +0100 Subject: [PATCH 7/8] fix test case --- src/__test__/nextRouterPagination.test.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/__test__/nextRouterPagination.test.tsx b/src/__test__/nextRouterPagination.test.tsx index 9c09db2..b9a9624 100644 --- a/src/__test__/nextRouterPagination.test.tsx +++ b/src/__test__/nextRouterPagination.test.tsx @@ -109,6 +109,9 @@ test('query multiple different properties, should keep them all', () => { act(() => { result.current.actions.updateQuery({ search: 'Max' }) + }) + + act(() => { result.current.actions.updateQuery({ department: 'IT' }) }) From b450726b97a3404114e867adaf6fd00f54b389b2 Mon Sep 17 00:00:00 2001 From: Martin Malfertheiner Date: Mon, 8 Nov 2021 11:43:30 +0100 Subject: [PATCH 8/8] update readme --- readme.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/readme.md b/readme.md index 97459b9..9e4f7b7 100644 --- a/readme.md +++ b/readme.md @@ -1,13 +1,13 @@ React Pagination ============= -This package includes pagination hooks for React. The hooks support saving the search and pagination values in local +This package includes pagination hooks for React. The hooks support saving the query and pagination values in local state or in the browser URL. ## Table of content - [Usage](#usage) - - [useSearchAndPagination](#usesearchandpagination) + - [useQueryAndPagination](#usequeryandpagination) - [Supported Implementations](#supported-implementations) - [In Memory Pagination](#in-memory-pagination) - [React-Router based pagination](#react-router-based-pagination) @@ -23,7 +23,7 @@ First, you have to install the package: npm install @aboutbits/react-pagination ``` -Second, you can make use of the `useSearchAndPagination` hook. This package implements 3 versions of this hook: +Second, you can make use of the `useQueryAndPagination` hook. This package implements 3 versions of this hook: - [In Memory](#in-memory-pagination): Use this hook where you don't want to modify browser history. e.g. Dialogs - [React Router](#react-router-based-pagination): Use this hook if you want to keep track of the state in the URL and @@ -31,9 +31,9 @@ Second, you can make use of the `useSearchAndPagination` hook. This package impl - [NextJS Router](#nextjs-router-based-pagination): Use this hook if you want to keep track of the state in the URL and your project is using NextJS. -### useSearchAndPagination +### useQueryAndPagination -This hook supports the combination of a search value and pagination and manages the state of the search value, and the +This hook supports the combination of query parameters and pagination and manages the state of the query parameter values and the pagination values. #### The hook supports following configuration parameter object: @@ -42,31 +42,32 @@ pagination values. |---|---|---|---| |indexType|IndexType|IndexType.ZERO_BASED|It defines whether the pagination is zero or one based.| |pageSize|number|15|Page size of the pagination.| +|defaultQueryParameters/Record|{}|It defines the default value for each query parameter. This is used to remove a query parameter from the URL and also to clear the query. #### The hook returns the following object: |value|type|description| |---|---|---| -|search|string|value of your search parameter| +|queryParameters|object|values of your query parameters| |page|number|value of the current page| |size|number|max elements in a single page| -|actions|object|object with 3 functions: search, setPage, clear| +|actions|object|object with 3 functions: updateQuery, setPage, clear| #### Example usage with NextJS ```tsx -import { useSearchAndPagination } from '@aboutbits/react-pagination/dist/nextRouterPagination' +import { useQueryAndPagination } from '@aboutbits/react-pagination/dist/nextRouterPagination' const users = [ 'Alex', 'Simon', 'Natan', 'Nadia', 'Moritz', 'Marie' ] function UserList() { - const { page, size, search, actions } = useSearchAndPagination({pageSize: 2}) + const { page, size, queryParameters, actions } = useQueryAndPagination({pageSize: 2}) return (
- actions.search(value)}/> + actions.updateQuery({search: value})}/>
    - {users.filter(user => user.startsWith(search)) + {users.filter(user => user.startsWith(queryParameters.search)) .slice(page, page + size) .map(user =>
  • {user}
  • )}
@@ -96,7 +97,7 @@ This package includes 3 different implementations of the above hook. Use this pagination hook if you want to keep track of the pagination in memory. This is very handy for dialogs. ```tsx -import { useSearchAndPagination } from '@aboutbits/react-pagination/dist/inMemoryPagination' +import { useQueryAndPagination } from '@aboutbits/react-pagination/dist/inMemoryPagination' ``` ### React-Router based pagination @@ -104,7 +105,7 @@ import { useSearchAndPagination } from '@aboutbits/react-pagination/dist/inMemor These are specific hooks for applications that use [React Router](https://reactrouter.com/) for routing. ```tsx -import { useSearchAndPagination } from '@aboutbits/react-pagination/dist/reactRouterPagination' +import { useQueryAndPagination } from '@aboutbits/react-pagination/dist/reactRouterPagination' ``` ### NextJS Router based pagination @@ -113,7 +114,7 @@ These are specific hooks for applications that use [NextJS Router](https://nextj for routing. ```tsx -import { useSearchAndPagination } from '@aboutbits/react-pagination/dist/nextRouterPagination' +import { useQueryAndPagination } from '@aboutbits/react-pagination/dist/nextRouterPagination' ``` ## Build & Publish