11import { useCallback , useMemo } from 'react'
2+ import { queryValueToIntOrUndefined } from './utils'
23
34export type Query = Record < string , string | string [ ] >
45
5- export type AbstractQueryValue = string | number | boolean
6+ export type AbstractQueryValueElement = string | number | boolean
67
78export type AbstractQuery = Record <
89 string ,
9- AbstractQueryValue | AbstractQueryValue [ ]
10+ AbstractQueryValueElement | AbstractQueryValueElement [ ]
1011>
1112
1213/**
@@ -28,11 +29,6 @@ export type Router = {
2829 * If the query is bound to the URL, the router navigates to the new URL.
2930 */
3031 setQuery : ( query : Partial < Query > ) => void
31-
32- /**
33- * Completely clears the query.
34- */
35- clearQuery : ( ) => void
3632}
3733
3834export const useQuery = < T extends Query > ( defaultQuery : T , router : Router ) => {
@@ -41,90 +37,115 @@ export const useQuery = <T extends Query>(defaultQuery: T, router: Router) => {
4137 [ router , defaultQuery ]
4238 )
4339
44- const clearQuery = useCallback ( ( ) => router . clearQuery ( ) , [ router ] )
45-
4640 const query = useMemo ( ( ) => router . getQuery ( ) , [ router ] )
4741
4842 return {
4943 query,
5044 setQuery : ( query : Partial < T > ) => router . setQuery ( query ) ,
5145 resetQuery,
52- clearQuery,
5346 }
5447}
5548
56- const abstractQueryToQuery = < T extends Partial < AbstractQuery > > (
57- abstractQuery : T
58- ) => {
59- const query : Query = { }
60- for ( const [ key , value ] of Object . entries ( abstractQuery ) ) {
61- if ( value !== undefined ) {
62- query [ key ] = value . toString ( )
49+ type AbstractQueryOptions = {
50+ convertToQuery : < T extends Partial < AbstractQuery > > ( abstractQuery : T ) => Query
51+ }
52+
53+ const DEFAULT_ABSTRACT_QUERY_OPTIONS : AbstractQueryOptions = {
54+ convertToQuery : ( abstractQuery ) => {
55+ const query : Query = { }
56+ for ( const [ key , value ] of Object . entries ( abstractQuery ) ) {
57+ if ( value !== undefined ) {
58+ query [ key ] = value . toString ( )
59+ }
6360 }
64- }
65- return query
61+ return query
62+ } ,
6663}
6764
6865export const useAbstractQuery = < T extends AbstractQuery > (
6966 defaultQuery : T ,
67+ parseQuery : ParseQuery < T > ,
7068 router : Router ,
71- parse : ParseQuery < T >
69+ options ?: Partial < AbstractQueryOptions >
7270) => {
71+ const mergedOptions = useMemo (
72+ ( ) => ( { ...DEFAULT_ABSTRACT_QUERY_OPTIONS , ...options } ) ,
73+ [ options ]
74+ )
75+
7376 const convertedDefaultQuery = useMemo (
74- ( ) => abstractQueryToQuery ( defaultQuery ) ,
75- [ defaultQuery ]
77+ ( ) => mergedOptions . convertToQuery ( defaultQuery ) ,
78+ [ mergedOptions , defaultQuery ]
7679 )
7780
78- const { query, setQuery, resetQuery, clearQuery } = useQuery (
81+ const { query, setQuery, resetQuery } = useQuery (
7982 convertedDefaultQuery ,
8083 router
8184 )
8285
83- const parsedQuery = useMemo ( ( ) => {
86+ const parsedQuery : T = useMemo ( ( ) => {
8487 let parsed : Partial < T >
8588 try {
86- parsed = parse ( query )
89+ parsed = parseQuery ( query )
8790 } catch ( e ) {
8891 parsed = { }
8992 }
9093 return {
9194 ...defaultQuery ,
9295 ...parsed ,
9396 }
94- } , [ defaultQuery , parse , query ] )
97+ } , [ defaultQuery , parseQuery , query ] )
9598
9699 const setAbstractQuery = useCallback (
97- ( query : Partial < T > ) => setQuery ( abstractQueryToQuery ( query ) ) ,
98- [ setQuery ]
100+ ( query : Partial < T > ) => setQuery ( mergedOptions . convertToQuery ( query ) ) ,
101+ [ setQuery , mergedOptions ]
99102 )
100103
101104 return {
102105 query : parsedQuery ,
103106 setQuery : setAbstractQuery ,
104107 resetQuery,
105- clearQuery,
106108 }
107109}
108110
109111export type PaginationQuery = { page : number ; size : number }
110112
111- export const usePagination = (
112- defaultQuery : PaginationQuery ,
113- router : Router ,
114- parse : ParseQuery < PaginationQuery >
113+ const parsePagination = ( query : Query ) : Partial < PaginationQuery > => {
114+ return {
115+ page : queryValueToIntOrUndefined ( query . page ) ,
116+ size : queryValueToIntOrUndefined ( query . size ) ,
117+ }
118+ }
119+
120+ export const useQueryAndPagination = < T extends AbstractQuery > (
121+ defaultQuery : T ,
122+ parseQuery : ParseQuery < T > ,
123+ defaultPagination : PaginationQuery ,
124+ router : Router
115125) => {
116- const { query, setQuery, resetQuery, clearQuery } = useAbstractQuery (
126+ const { query, setQuery, resetQuery } = useAbstractQuery (
117127 defaultQuery ,
118- router ,
119- parse
128+ parseQuery ,
129+ router
120130 )
121131
132+ const {
133+ query : pagination ,
134+ setQuery : setPagination ,
135+ resetQuery : resetPagination ,
136+ } = useAbstractQuery ( defaultPagination , parsePagination , router )
137+
122138 return {
123- page : query . page ,
124- size : query . size ,
125- setSize : ( size : PaginationQuery [ 'size' ] ) => setQuery ( { size } ) ,
126- setPage : ( page : PaginationQuery [ 'page' ] ) => setQuery ( { page } ) ,
127- resetPagination : resetQuery ,
128- clearQuery,
139+ query,
140+ setQuery,
141+ resetQuery,
142+ page : pagination . page ,
143+ size : pagination . size ,
144+ setPage : ( page : PaginationQuery [ 'page' ] ) => setPagination ( { page } ) ,
145+ setSize : ( size : PaginationQuery [ 'size' ] ) => setPagination ( { size } ) ,
146+ setPagination,
147+ resetPagination,
148+ resetQueryAndPagination : ( ) =>
149+ setQuery ( { ...defaultQuery , ...defaultPagination } ) ,
129150 }
130151}
0 commit comments