I have implemented a data table using the DevExtreme DataGrid in React. The table has over 6000 records and more than 160 columns. Here’s how it works:
Initially, I load only the column names.
Upon clicking a button, all the records are fetched from an API.
The table uses virtual scrolling for better performance.
However, I’m facing an issue where skeleton loaders appear both above and below the viewport while scrolling, which creates a weird visual effect. Here’s a simplified version of my code:
import React, { memo } from "react";
import DataGrid, {
Column,
ColumnChooser,
Export,
Paging,
Scrolling,
SearchPanel,
Selection,
Sorting,
Summary,
TotalItem
} from "devextreme-react/data-grid";
import PropTypes from "prop-types"; // Import PropTypes
const DataGridComponent = memo((props) => {
const {
data,
keyExpr,
onSelectionChanged,
selectedRows,
columns,
stickyIndex,
summaryItems,
extraColumn,
onIconClick,
cellRender,
height
} = props;
// Memoize data to avoid re-renders on each row selection change
const memoizedData = React.useMemo(() => data, [data]);
// Memoize columns (if an extra column is provided)
const memoizedColumns = React.useMemo(() => {
return extraColumn ? [extraColumn, ...columns] : columns;
}, [extraColumn, columns]);
const memoizedCellRender = React.useCallback((e, col) => {
if (cellRender) {
return cellRender(e, col);
}
}, [cellRender]);
// Detect if the screen is mobile
const isMobile = React.useMemo(() => window.innerWidth <= 768, []);
return (
<div style={{ height: "100%", display: "flex", flexDirection: "column", padding: "10px 0" }}>
<DataGrid
dataSource={memoizedData}
animation={{ enabled: false }}
keyExpr={keyExpr}
showBorders={true}
allowColumnResizing={false}
columnAutoWidth={true}
height={height}
onSelectionChanged={(e) => onSelectionChanged(e?.selectedRowKeys)}
selectedRowKeys={selectedRows}
showColumnLines={true}
loadPanel={{
enabled: false,
showIndicator: true,
}}
>
<ColumnChooser enabled />
<Selection mode="multiple" showCheckBoxesMode="always" />
<Scrolling mode="virtual" />
<Paging enabled={false} />
<Sorting mode="multiple" />
<SearchPanel visible highlightCaseSensitive />
<Export enabled />
{Array.isArray(memoizedColumns) && memoizedColumns.map((col, index) => (
<Column
key={index}
fixed={!isMobile && index < stickyIndex} // Disable fixed columns on mobile
fixedPosition="left"
dataField={col.accessorKey}
caption={col.header}
visible={col.is_visible}
alignment={col.textAlign}
allowFiltering={true}
allowSorting={true}
cellRender={(e) => memoizedCellRender(e, col)}
/>
))}
<Summary>
{summaryItems.map((item, index) => (
<TotalItem
key={index}
column={item.column}
summaryType={item.summaryType}
displayFormat={item.displayFormat}
skipEmptyValues={false}
/>
))}
</Summary>
</DataGrid>
</div>
);
});
// Define PropTypes
DataGridComponent.propTypes = {
data: PropTypes.array,
keyExpr: PropTypes.string,
onSelectionChanged: PropTypes.func,
selectedRows: PropTypes.array,
columns: PropTypes.array,
stickyIndex: PropTypes.number,
summaryItems: PropTypes.array,
loading: PropTypes.bool,
onIconClick: PropTypes.func,
cellRender: PropTypes.func,
};
// Set default props to avoid crashes
DataGridComponent.defaultProps = {
data: [],
keyExpr: "diamond_id",
onSelectionChanged: () => { },
selectedRows: [],
columns: [],
stickyIndex: 0,
summaryItems: [],
loading: true,
onIconClick: () => { },
cellRender: null
};
export default DataGridComponent;
Key Points:
I’m using virtual scrolling mode.
Skeleton loaders show up awkwardly during scrolling.
The issue is noticeable because of the large dataset and many columns.
What I’ve Tried:
Disabling animations using animation: { enabled: false }.
Optimizing data and column rendering using useMemo.
Questions:
- Is there a way to prevent skeleton loaders from appearing above and below the viewport while scrolling?
- Are there additional optimizations for handling large datasets and many columns with the DevExtreme DataGrid?
Any suggestions or best practices for improving the scrolling behavior and overall performance would be greatly appreciated!
What I Tried:
- I disabled animations in the DataGrid using
animation: { enabled: false }
. - I used
React.useMemo
to optimize the rendering of both data and columns. - I configured the grid to use virtual scrolling with
scrolling: { mode: "virtual" }
.
What I Expected:
I expected smoother scrolling with no skeleton loaders or rendering artifacts, ensuring a seamless user experience even with large datasets and many columns.
What Actually Happened:
Despite these optimizations, skeleton loaders still appear above and below the viewport during scrolling, creating a visually unappealing experience.