Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MUI X Data Grid performance issues

I'm using MUI X Data Grid to display my records but there is this delay happening to take place for my modal and drawer. I even tried useMemo for my columns but couldn't achieve a better result. enter image description here

Selection.tsx:

import * as React from 'react';
import { DataGrid, faIR, GridSelectionModel } from '@mui/x-data-grid';
import type {} from '@mui/x-data-grid/themeAugmentation';
import { createTheme, makeStyles, ThemeProvider } from '@mui/material/styles';
import { useRef, useState } from "react";
import { TablePagination } from "@mui/material";
import Stack from "@mui/material/Stack";
import DeleteIcon from '@mui/icons-material/Delete';


export default function ControlledSelectionServerPaginationGrid(props: any) {
  const theme = createTheme(
    {
      breakpoints: {
        values: {
          xs: 300,
          sm: 600,
          md: 900,
          lg: 1200,
          xl: 1536
        }
      },
      palette: {
        primary: { main: '#1976d2' },
      },
      components: {
        MuiDataGrid: {
            styleOverrides: {
              root: {
                display: "flex",
                flexDirection: "column-reverse",
                borderRadius: '0',
                paddingRight: '0px',
              },
              menu: {
                  direction: "rtl",
              },
              footerContainer: {
                borderBottom: '1px solid #e0e0e0'
              },
                cell: {
                textAlign: 'right',
                '&:last-child': {
                  textAlign: 'center',
                },
              }


            }
        },
        MuiTablePagination: {
          styleOverrides: {
            root: {
              borderRadius: 'none',
              direction: 'rtl',
            },
            displayedRows: {
              margin: 0,
              direction: 'ltr',
            },
            actions: {
            direction: "ltr"
            }
          }

        },
        MuiToolbar: {
          styleOverrides: {
            root: {
              display: 'flex',
              flexDirection: 'row-reverse',
            }
          }
        },
        MuiTableCell: {
          styleOverrides: {
            root: {
              border: 'none'
            }
          }
        }
      },
    },
    faIR,
  );


  const [page, setPage] = useState<number>(0);
  const { packages, loading } = props.FetchData(page);
  const [selected, setSelected] = useState<any>([]);
  const [rowsPerPage, setRowsPerPage] = useState<number>(15);


  const handleChangePage = (event: React.MouseEvent<HTMLButtonElement> | null, pageNumber: number) => {
    setPage(pageNumber);
  };

  const handleChangeRowsPerPage = (
    event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
  ) => {
    setRowsPerPage(parseInt(event.target.value));
    setPage(0);
  };


  const CustomFooter = () => {
    return (
        <Stack
          direction="row"
          justifyContent="space-between"
          alignItems="center"
          sx={{
            borderBottom: '1px solid #e0e0e0'
          }}
        >
          <Stack
            direction="row"
            justifyContent="space-between"
            alignItems="center"
            sx={{
              marginRight: '20px',
            }}
          >
            {
              selected && selected.length > 0 && (
                  <DeleteIcon sx={{color: "gray", cursor: 'pointer'}} onClick={() => alert('deleted them all')} />
              )
            }
          </Stack>
          <CustomPagination/>
        </Stack>
    )
  }

  const CustomPagination = () => {
    return (
      <TablePagination
        count={packages?.meta?.last_page}
        page={page}
        onPageChange={handleChangePage}
        rowsPerPage={rowsPerPage}
        labelRowsPerPage={false}
        onRowsPerPageChange={handleChangeRowsPerPage}
        rowsPerPageOptions={[15, 30, 45, 60]}
      />
    )
  }

  return (
    <div style={{ height: '790px', width: '100%' }}>
      <ThemeProvider theme={theme}>
        {
          loading ? (
              <div>
                loading
              </div>
          ) : (
              <DataGrid
                rows={packages.data}
                getRowId={(row) => row.uuid}
                columns={props.columns}
                pagination
                components={{Footer: CustomFooter}}
                checkboxSelection
                disableSelectionOnClick
                hideFooterSelectedRowCount
                loading={loading}
                onSelectionModelChange={(ids) => {
                  setSelected(ids);
                }}
              />
          )
        }
      </ThemeProvider>

    </div>
  );
}

I have the below hook as well which I'm passing to the above component as FetchData:

usePackages.tsx:

export default function usePackages(page: number) {
  const [loading, setLoading] = useState<boolean>(false);
  const [packages, setPackages] = useState<any>({
    data: [],
    meta: {},
    links: {}
  });

  useEffect(() => {
    setLoading(true);
    getListOfAllPackages(page)
      .then(data => {
        setPackages({
          ...data.data,
        });
        setLoading(false);
      })
      .catch(error => {
        setLoading(false);
      });
  }, [page]);

  return { packages, loading };

Now the way I'm using the above components is just like below:

Packages.tsx:

import usePackages from "../../../hooks/Package/usePackages";

     const configValues = (params: any) => {
        return `${params.row.config.hdd}, ${params.row.config.cpu}, ${params.row.config.ram}`
      }
      
      const columns = [
        {
          field: "product_name",
          headerName: "Product Name",
          width: '200',
          flex: 1
        },
        {
          field: "name",
          headerName: "Name",
          width: '400',
          flex: 1
        },
        {
          field: "config",
          headerName: "Config",
          width: '150',
          flex: 1,
          valueGetter: configValues,
        },
        {
          field: "description",
          headerName: "Description",
          width: '350',
          flex: 1
        },
        {
          field: 'actions',
          type: 'Actions',
          width: '100',
          flex: 1,
        },
      ]
    
    
      
    
      return (
        <div style={{ display: 'flex', height: '100%', marginTop: '64px'}}>
          <div style={{ flexGrow: 1 }}>
            <ControlledSelectionServerPaginationGrid columns={columns} FetchData={usePackages}/>
          </div>
        </div>
      )

I would really appreciate for any help or anyone with similar experience, Should I even go for an alternative like React Tables?

like image 932
Mohammad A. Souri Avatar asked May 09 '26 11:05

Mohammad A. Souri


1 Answers

To solve this problem you have to wrap Drawer component within new AppDrawer component(name doesn`t matter), then put your DataGrid component inside the AppDrawer component as a child element, side by side with Drawer component. {children} inside Box component it is a DataTable. This resolve problem with lagy rerendering.

enter image description here

don`t forget to add as a props

export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
})

from parent component you need to provide this DataTable component as a children

  return (
<div>
  <DashboardDrawer
    open={isDrawerOpen}
    handleDrawerToggle={handleDrawerToggle}
  >
    <DataTable />
  </DashboardDrawer>
</div>

);

like image 127
Ramazan Avatar answered May 11 '26 00:05

Ramazan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!