Skip to content

Commit 307a4f1

Browse files
Adjusted useDataTable (certego#83)
* fix table * docs * typo * changes
1 parent f65e3cb commit 307a4f1

File tree

4 files changed

+48
-48
lines changed

4 files changed

+48
-48
lines changed

src/components/table/DataTable.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React from "react";
33
import PropTypes from "prop-types";
44
import classnames from "classnames";
55
import { Table } from "reactstrap";
6+
// react-table doc: https://react-table-v7-docs.netlify.app/
67
import { useTable, useMountedLayoutEffect } from "react-table";
78
import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa";
89

@@ -14,6 +15,9 @@ import {
1415
} from "./utils";
1516
import Paginator from "./Paginator";
1617

18+
/**
19+
* Suitable when data is already available client side. Thus, pagination/filtering/sorting can be performed client side too.
20+
*/
1721
function DataTable({
1822
config: userConfig,
1923
onSelectedRowChange,

src/components/table/queryParamsUtils.jsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,51 @@ These funcitions helps to convert from obj to string and vice versa
55
*/
66

77
/**
8+
* This function is used to convert filters from obj to string
89
* @argument {Array<Object>} filters
910
* @return {Object}
1011
*/
11-
const serializeFilterParams = (filters) =>
12+
const serializeFilterParams = (filters) =>
1213
filters.reduce(
13-
// id and value connot be changed, are requested with this name in the lib
1414
(acc, { id, value, }) => ({ ...acc, [id]: value, }),
1515
{}
1616
);
1717

1818
/**
19+
* This function is used to convert filters from string to obj
1920
* @argument {Object} filters
2021
* @return {Array<Object>}
2122
*/
2223
const deserializeFilterParams = (filters) =>
2324
Array.from(
24-
Object.entries(filters).map(([filterName, filterValue]) => ({
25-
id: filterName,
25+
Object.entries(filters).map(([filterKey, filterValue]) => ({
26+
id: filterKey,
2627
value: filterValue,
2728
}))
2829
);
2930

3031
/**
32+
* This function is used to convert ordering key from obj to string
3133
* @argument {Array<Object>} sortBy
3234
* @return {String}
3335
*/
3436
const serializeSortByParams = (sortBy) =>
3537
sortBy
36-
// id and desc connot be changed, are requested with this name in the lib
3738
.map(({ id, desc, }) => `${desc ? "-" : ""}${id.split("-")[0]}`)
3839
.join(",");
3940

4041
/**
42+
* This function is used to convert ordering key from string to obj
4143
* @argument {String} filters
4244
* @return {Array<Object>}
4345
*/
44-
const deserializeSortByParams = (sortByStr) => ({
45-
id: sortByStr.charAt(0) === "-" ? sortByStr.slice(1) : sortByStr,
46-
desc: sortByStr.charAt(0) === "-",
47-
});
46+
const deserializeSortByParams = (sortByStr) =>
47+
Array.from(
48+
sortByStr.split(",").map((str) => ({
49+
id: str.charAt(0) === "-" ? str.slice(1) : str,
50+
desc: str.charAt(0) === "-",
51+
}))
52+
);
4853

4954
export {
5055
serializeFilterParams,

src/components/table/useDataTable.jsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,34 @@ import LoadingBoundary from "../containers/LoadingBoundary";
66
import DataTable from "./DataTable";
77
import useQueryParamsTable from "./useQueryParamsTable";
88

9-
const pageParams = {
9+
const defaultPageParams = {
1010
page_size: 10,
1111
page: 1,
1212
};
13-
const defaultModifier = (d) => d?.results || [];
13+
const defaultModifier = (responseData) => responseData?.results || [];
1414

15+
/**
16+
* Suitable for fetching data from a server. Thus, pagination/filtering/sorting in most cases should be handled by the server too.
17+
* @param url URL to use to make the request.
18+
* @param params Query parameters that will be added to the request, which can be overridden by table filters.
19+
* @param toPassTableProps Table properties (ex. columns, config, initialState, SubComponent) that will be used for creating the table component.
20+
* @param modifier Function that defines in which field of the response the data that will be used is located.
21+
*/
1522
function useDataTable(
16-
{ url, params: defaultParams, initialParams, },
23+
{ url, params: defaultParams, },
1724
toPassTableProps,
1825
modifier = defaultModifier
1926
) {
20-
/*
21-
*/
22-
const columnNames = toPassTableProps.columns.map(column => column.accessor);
2327
// hook
24-
const [params, tableInitialState, tableStateReducer] = useQueryParamsTable({
25-
initialParams, columnNames,
26-
});
28+
const [params, tableInitialState, tableStateReducer] = useQueryParamsTable();
2729

2830
// state
2931
const [initialLoading, setInitialLoading] = React.useState(true);
3032

3133
// API
3234
const [{ data, loading, error, }, refetch] = useAxios({
3335
url,
34-
params: { ...pageParams, ...defaultParams, ...params, },
36+
params: { ...defaultPageParams, ...defaultParams, ...params, },
3537
});
3638

3739
// side-effects
@@ -74,7 +76,7 @@ function useDataTable(
7476
]
7577
);
7678

77-
return [data, tableNode, refetch, tableStateReducer, loading];
79+
return [data, tableNode, refetch, tableStateReducer, loading, tableInitialState];
7880
}
7981

8082
export default useDataTable;

src/components/table/useQueryParamsTable.jsx

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,24 @@ import {
99
deserializeSortByParams
1010
} from "./queryParamsUtils";
1111

12-
function useQueryParamsTable({ initialParams, columnNames, }) {
12+
/**
13+
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.
14+
*/
15+
function useQueryParamsTable() {
1316
// react-router
1417
const navigate = useNavigate();
1518
const location = useLocation();
1619

17-
// state
18-
/*
19-
initialParams is used for
20-
fallback values incase URL query params are empty
21-
*/
20+
// Set the params based on url search params, if no parameter is set in the url it returns an empty dict
2221
const [params, setParams] = React.useState(() => {
2322
const urlParams = Object.fromEntries(
2423
new URLSearchParams(location.search)
2524
);
26-
return Object.keys(urlParams).length ? urlParams : initialParams || {};
25+
return Object.keys(urlParams).length ? urlParams : {};
2726
});
2827

29-
// memo
30-
const initialState = React.useMemo(() => {
28+
// The table state changes every time the url params are modified, therefore every time some filters are modified
29+
const tableInitialState = React.useMemo(() => {
3130
const { ordering, page, ...filters } = params;
3231
return {
3332
pageIndex: page ? parseInt(page - 1, 10) : 0,
@@ -36,7 +35,7 @@ function useQueryParamsTable({ initialParams, columnNames, }) {
3635
};
3736
}, [params]);
3837

39-
// update query params to match table state
38+
// Update query params to match table state and navigate to a page with the new params
4039
React.useEffect(() => {
4140
const search = `?${new URLSearchParams(params).toString()}`;
4241
if (search !== location.search)
@@ -45,21 +44,11 @@ function useQueryParamsTable({ initialParams, columnNames, }) {
4544

4645
// callbacks
4746
const onTableFilterDebounced = useAsyncDebounce(
48-
/* this function MUST updates ONLY the parameters used by the table: the columns.
49-
It has to maintain all the params used in the page outside the table.
50-
*/
51-
(filters) =>
52-
53-
setParams(({ ordering, ...others }) => ({ // we need to separate ordering, or this doesn't work
54-
// Maintain the parameter
55-
...Object.keys(others)
56-
.filter(param => !!columnNames.includes(param.id)) // select only parameter external to the table
57-
.reduce((savedParams, nextParam) => ({...savedParams, [nextParam[0]]: nextParam[1], }), {}), // concatenate them
58-
// Add ordering parameter (if it's defined)
59-
...(ordering ? { ordering, } : {}),
60-
// add the filter parameters (the ones with columns names)
61-
...serializeFilterParams(filters.filter(filter => columnNames.includes(filter.id))),
62-
})),
47+
(filters) =>
48+
setParams(({ ordering, }) => ({
49+
...(ordering ? { ordering, } : {}), // only include 'ordering' key if it defined
50+
...serializeFilterParams(filters), // only serialize 'filters' field
51+
})),
6352
500
6453
); // Debounce filter call for 500ms
6554

@@ -68,9 +57,9 @@ function useQueryParamsTable({ initialParams, columnNames, }) {
6857
sortBy?.length
6958
? setParams(({ ordering, ...others }) => ({
7059
...others,
71-
ordering: serializeSortByParams(sortBy),
60+
ordering: serializeSortByParams(sortBy), // override only 'ordering' key
7261
}))
73-
: setParams(({ ordering, ...others }) => others),
62+
: setParams(({ ordering, ...others }) => others), // if sortBy has been reset remove the 'orgering' key
7463
500
7564
); // Debounce sortBy call for 500ms
7665

@@ -97,7 +86,7 @@ function useQueryParamsTable({ initialParams, columnNames, }) {
9786
[setParams, onTableFilterDebounced, onTableSortDebounced]
9887
);
9988

100-
return [params, initialState, tableStateReducer];
89+
return [params, tableInitialState, tableStateReducer];
10190
}
10291

10392
export default useQueryParamsTable;

0 commit comments

Comments
 (0)