Introduction
Good afternoon everyone. My name is Alexander. Now I work at Megafon as a front-end developer. Data retrieval problems have always been particularly complex and often non-standard in approaches. Today I would like to focus on one interesting problem that I had to solve quite recently during the development of the IoT platform. However, such a task can also be encountered on any other project where there is a dynamic data loading via the REST API. Whether it is loading during pagination, or during scrolling, or something else ...
Problematic
It would seem: what could be the difficulty. Especially when it comes only to the front? After all, all search algorithms are implemented mainly on the back-end. In fact, yes and no. Let's imagine a simple spreadsheet that has multiple pages pagination and a filter on each column. See below.
In this plate, the filter by the BS number column is open. In simple words: by entering any characters in the filter input field, you get the appropriate options in the dropdown. By clicking on any of them, you will filter the data in the table by this element.
How can you display such a dropdown with the necessary options?
Solution options
filter includes ( ) . , , . . .
1- , . , 0. 1 ? .
, . ââ , .
. . : , , .
, , . config.
. , debounce.
/ loader
, JS React , , JS. .
, . , ( ) . 2 .
:
{
id: 'address',
title: ' ',
filter: filters.address,
checked: true,
minWidth: 160
}
:
address: {
type: 'includes',
name: 'addrFilter',
options: {
default: {
values: 'objectsList',
fetchFunc: 'fetchObjectsList',
calcFunc: 'address'
}
}
}
- . .
options . :
fetchFunc - thunk ,
values - ,
calcFunc -
calcFun. , . , . : = + + âĶ
. :
//object includes calc functions
const calculatedData = useMemo(() => (
{
default: (values) =>
{
//default calculate
},
address: (values) =>
{
//calculate with generateAddress function, for example
},
...
}
), [...]);
//using this object (calcFunc from config):
const data = calculatedData[calcFunc || 'default'](values)
. . , - . :
// debounce function
const debounce = (fn, ms = 0) => {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), ms);
};
};
//debounceFetch function
const debounceFetch = debounce(async (func, args) =>
typeof func === 'function' && (await func(args)), 500);
//sending request
useEffect(() => {
debounceFetch(actions[fetchFunc], {
filter: { [filterName]: filterValue || null }
});
}, [filter]);
. - , , . , , , isLoading. , isLoadingObjects. selector kea, = true , isLoading, true.
kea, redux - - , . - . kea =)
anyLoading===true, .
. , , calcFunc .
, , useFiltersOptions.
, : , , . , , .
, , .