mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01:00
feat: Refactor Table State Persistence in Feature Toggle List (#5527)
new custom hook, `usePersistentTableState` Co-authored-by: Mateusz Kwasniewski <kwasniewski.mateusz@gmail.com>
This commit is contained in:
parent
a0a15416c4
commit
a506b92544
@ -46,13 +46,9 @@ import {
|
|||||||
useFeatureSearch,
|
useFeatureSearch,
|
||||||
} from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
|
} from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
|
||||||
import mapValues from 'lodash.mapvalues';
|
import mapValues from 'lodash.mapvalues';
|
||||||
import {
|
import { NumberParam, StringParam, withDefault } from 'use-query-params';
|
||||||
BooleanParam,
|
import { BooleansStringParam } from 'utils/serializeQueryParams';
|
||||||
NumberParam,
|
import { usePersistentTableState } from 'hooks/usePersistentTableState';
|
||||||
StringParam,
|
|
||||||
useQueryParams,
|
|
||||||
withDefault,
|
|
||||||
} from 'use-query-params';
|
|
||||||
|
|
||||||
export const featuresPlaceholder = Array(15).fill({
|
export const featuresPlaceholder = Array(15).fill({
|
||||||
name: 'Name of the feature',
|
name: 'Name of the feature',
|
||||||
@ -76,14 +72,19 @@ export const FeatureToggleListTable: VFC = () => {
|
|||||||
|
|
||||||
const { setToastApiError } = useToast();
|
const { setToastApiError } = useToast();
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const [tableState, setTableState] = useQueryParams({
|
|
||||||
|
const [tableState, setTableState] = usePersistentTableState(
|
||||||
|
'features-list-table',
|
||||||
|
{
|
||||||
offset: withDefault(NumberParam, 0),
|
offset: withDefault(NumberParam, 0),
|
||||||
limit: withDefault(NumberParam, DEFAULT_PAGE_LIMIT),
|
limit: withDefault(NumberParam, DEFAULT_PAGE_LIMIT),
|
||||||
query: StringParam,
|
query: StringParam,
|
||||||
favoritesFirst: withDefault(BooleanParam, true),
|
favoritesFirst: withDefault(BooleansStringParam, true),
|
||||||
sortBy: withDefault(StringParam, 'createdAt'),
|
sortBy: withDefault(StringParam, 'createdAt'),
|
||||||
sortOrder: withDefault(StringParam, 'desc'),
|
sortOrder: withDefault(StringParam, 'desc'),
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
features = [],
|
features = [],
|
||||||
total,
|
total,
|
||||||
|
40
frontend/src/hooks/usePersistentTableState.ts
Normal file
40
frontend/src/hooks/usePersistentTableState.ts
Normal file
@ -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
frontend/src/utils/serializeQueryParams.ts
Normal file
30
frontend/src/utils/serializeQueryParams.ts
Normal file
@ -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,
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user