11import React from 'react' ;
22
3- import type { Column , DataTableProps , Settings , SortOrder } from '@gravity-ui/react-data-table' ;
3+ import type { Column , DataTableProps , SortOrder } from '@gravity-ui/react-data-table' ;
44import DataTable , { updateColumnsWidth } from '@gravity-ui/react-data-table' ;
55import { Skeleton } from '@gravity-ui/uikit' ;
66
77import { cn } from '../../utils/cn' ;
88import { useTableResize } from '../../utils/hooks/useTableResize' ;
9+ import { TableSkeleton } from '../TableSkeleton/TableSkeleton' ;
910
1011import './ResizeableDataTable.scss' ;
1112
@@ -14,7 +15,19 @@ const b = cn('ydb-resizeable-data-table');
1415export interface ResizeableDataTableProps < T > extends Omit < DataTableProps < T > , 'theme' | 'onResize' > {
1516 columnsWidthLSKey ?: string ;
1617 wrapperClassName ?: string ;
17- loading ?: boolean ;
18+
19+ /**
20+ * Not enough meta data (settings, sizes, features, etc.) to properly render table columns
21+ * Use case: initial load
22+ */
23+ isLoading ?: boolean ;
24+ /**
25+ * No table data, but columns data is loaded and they could be rendered
26+ * Use case: you need to preserve table headers on sort change when backend sort
27+ */
28+ isFetching ?: boolean ;
29+ loadingSkeletonRowsCount ?: number ;
30+
1831 onSortChange ?: ( params : SortOrder | SortOrder [ ] | undefined ) => void ;
1932}
2033
@@ -23,9 +36,12 @@ export function ResizeableDataTable<T>({
2336 columns,
2437 settings,
2538 wrapperClassName,
26- loading,
39+ isLoading,
40+ isFetching,
41+ loadingSkeletonRowsCount = 2 ,
2742 onSort,
2843 onSortChange,
44+ data,
2945 ...props
3046} : ResizeableDataTableProps < T > ) {
3147 const [ tableColumnsWidth , setTableColumnsWidth ] = useTableResize ( columnsWidthLSKey ) ;
@@ -39,19 +55,36 @@ export function ResizeableDataTable<T>({
3955 ) ;
4056
4157 // If loading is true, override the render method of each column to display a Skeleton
42- const processedColumns = loading
43- ? columns . map ( ( column : Column < T > ) => ( {
44- ...column ,
45- render : ( ) => < Skeleton className = { b ( 'row-skeleton' ) } /> ,
46- } ) )
47- : columns ;
58+ const processedColumns = React . useMemo ( ( ) => {
59+ if ( isFetching ) {
60+ return columns . map ( ( column : Column < T > ) => ( {
61+ ...column ,
62+ render : ( ) => < Skeleton className = { b ( 'row-skeleton' ) } /> ,
63+ } ) ) ;
64+ }
65+ return columns ;
66+ } , [ isFetching , columns ] ) ;
4867
4968 const updatedColumns = updateColumnsWidth ( processedColumns , tableColumnsWidth ) ;
5069
51- const newSettings : Settings = {
52- ...settings ,
53- defaultResizeable : true ,
54- } ;
70+ const processedData = React . useMemo ( ( ) => {
71+ if ( isFetching && ! data ?. length ) {
72+ // We do not use data in render method when loading, so we can return an array of empty objects
73+ return Array . from ( { length : loadingSkeletonRowsCount } , ( ) => ( { } ) as T ) ;
74+ }
75+ return data ;
76+ } , [ isFetching , data , loadingSkeletonRowsCount ] ) ;
77+
78+ const newSettings = React . useMemo ( ( ) => {
79+ return {
80+ ...settings ,
81+ defaultResizeable : true ,
82+ } ;
83+ } , [ settings ] ) ;
84+
85+ if ( isLoading ) {
86+ return < TableSkeleton rows = { loadingSkeletonRowsCount } /> ;
87+ }
5588
5689 return (
5790 < div className = { b ( null , wrapperClassName ) } >
@@ -61,6 +94,7 @@ export function ResizeableDataTable<T>({
6194 onResize = { setTableColumnsWidth }
6295 onSort = { handleSort }
6396 settings = { newSettings }
97+ data = { processedData }
6498 { ...props }
6599 />
66100 </ div >
0 commit comments