-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathuseQueryParamsTable.jsx
More file actions
92 lines (82 loc) · 3 KB
/
useQueryParamsTable.jsx
File metadata and controls
92 lines (82 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import React from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { useAsyncDebounce } from "react-table";
import {
serializeFilterParams,
deserializeFilterParams,
serializeSortByParams,
deserializeSortByParams
} from "./queryParamsUtils";
/**
This function automatically defines the params to be used in the request based on the filters set in the table and the URL search parameters.
*/
function useQueryParamsTable() {
// react-router
const navigate = useNavigate();
const location = useLocation();
// Set the params based on url search params, if no parameter is set in the url it returns an empty dict
const [params, setParams] = React.useState(() => {
const urlParams = Object.fromEntries(
new URLSearchParams(location.search)
);
return Object.keys(urlParams).length ? urlParams : {};
});
// The table state changes every time the url params are modified, therefore every time some filters are modified
const tableInitialState = React.useMemo(() => {
const { ordering, page, ...filters } = params;
return {
pageIndex: page ? parseInt(page - 1, 10) : 0,
sortBy: ordering ? deserializeSortByParams(ordering) : [],
filters: filters ? deserializeFilterParams(filters) : [],
};
}, [params]);
// Update query params to match table state and navigate to a page with the new params
React.useEffect(() => {
const search = `?${new URLSearchParams(params).toString()}`;
if (search !== location.search)
navigate({ search, }, { replace: true, });
}, [navigate, params, location.search]);
// callbacks
const onTableFilterDebounced = useAsyncDebounce(
(filters) =>
setParams(({ ordering, }) => ({
...(ordering ? { ordering, } : {}), // only include 'ordering' key if it defined
...serializeFilterParams(filters), // only serialize 'filters' field
})),
500
); // Debounce filter call for 500ms
const onTableSortDebounced = useAsyncDebounce(
(sortBy) =>
sortBy?.length
? setParams(({ ordering, ...others }) => ({
...others,
ordering: serializeSortByParams(sortBy), // override only 'ordering' key
}))
: setParams(({ ordering, ...others }) => others), // if sortBy has been reset remove the 'orgering' key
500
); // Debounce sortBy call for 500ms
const tableStateReducer = React.useCallback(
(newState, action) => {
switch (action.type) {
case "gotoPage":
setParams((currParams) => ({
...currParams,
page: action.pageIndex + 1,
}));
break;
case "setFilter":
onTableFilterDebounced(newState.filters);
break;
case "toggleSortBy":
onTableSortDebounced(newState.sortBy);
break;
default:
break;
}
return newState;
},
[setParams, onTableFilterDebounced, onTableSortDebounced]
);
return [params, tableInitialState, tableStateReducer];
}
export default useQueryParamsTable;