Skip to content

Commit

Permalink
feat: Refactor Table State Persistence in Feature Toggle List (#5527)
Browse files Browse the repository at this point in the history
new custom hook, `usePersistentTableState`

Co-authored-by: Mateusz Kwasniewski <[email protected]>
  • Loading branch information
Tymek and kwasniew authored Dec 4, 2023
1 parent a0a1541 commit a506b92
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,9 @@ import {
useFeatureSearch,
} from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
import mapValues from 'lodash.mapvalues';
import {
BooleanParam,
NumberParam,
StringParam,
useQueryParams,
withDefault,
} from 'use-query-params';
import { NumberParam, StringParam, withDefault } from 'use-query-params';
import { BooleansStringParam } from 'utils/serializeQueryParams';
import { usePersistentTableState } from 'hooks/usePersistentTableState';

export const featuresPlaceholder = Array(15).fill({
name: 'Name of the feature',
Expand All @@ -76,14 +72,19 @@ export const FeatureToggleListTable: VFC = () => {

const { setToastApiError } = useToast();
const { uiConfig } = useUiConfig();
const [tableState, setTableState] = useQueryParams({
offset: withDefault(NumberParam, 0),
limit: withDefault(NumberParam, DEFAULT_PAGE_LIMIT),
query: StringParam,
favoritesFirst: withDefault(BooleanParam, true),
sortBy: withDefault(StringParam, 'createdAt'),
sortOrder: withDefault(StringParam, 'desc'),
});

const [tableState, setTableState] = usePersistentTableState(
'features-list-table',
{
offset: withDefault(NumberParam, 0),
limit: withDefault(NumberParam, DEFAULT_PAGE_LIMIT),
query: StringParam,
favoritesFirst: withDefault(BooleansStringParam, true),
sortBy: withDefault(StringParam, 'createdAt'),
sortOrder: withDefault(StringParam, 'desc'),
},
);

const {
features = [],
total,
Expand Down
40 changes: 40 additions & 0 deletions frontend/src/hooks/usePersistentTableState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import { createLocalStorage } from 'utils/createLocalStorage';
import { useQueryParams } from 'use-query-params';

const usePersistentSearchParams = (key: string) => {
const [searchParams, setSearchParams] = useSearchParams();
const { value, setValue } = createLocalStorage(key, {});
useEffect(() => {
const params = Object.fromEntries(searchParams.entries());
if (Object.keys(params).length > 0) {
return;
}
if (Object.keys(value).length === 0) {
return;
}

setSearchParams(value, { replace: true });
}, []);

return setValue;
};

export const usePersistentTableState = <
T extends Parameters<typeof useQueryParams>[0],
>(
key: string,
queryParamsDefinition: T,
) => {
const updateStoredParams = usePersistentSearchParams(key);

const [tableState, setTableState] = useQueryParams(queryParamsDefinition);

useEffect(() => {
const { offset, ...rest } = tableState;
updateStoredParams(rest);
}, [JSON.stringify(tableState)]);

return [tableState, setTableState] as const;
};
30 changes: 30 additions & 0 deletions frontend/src/utils/serializeQueryParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Custom additional serializers for query params library
// used in `useQueryParams` hook

const encodeBoolean = (
bool: boolean | null | undefined,
): string | null | undefined => {
if (bool == null) {
return bool;
}

return bool ? 'true' : 'false';
};

const decodeBoolean = (
input: string | (string | null)[] | null | undefined,
): boolean | null | undefined => {
if (input === 'true') {
return true;
}
if (input === 'false') {
return false;
}

return null;
};

export const BooleansStringParam = {
encode: encodeBoolean,
decode: decodeBoolean,
};

0 comments on commit a506b92

Please sign in to comment.