Home > database >  Adding skeleton effect to a table with sorting/pagination
Adding skeleton effect to a table with sorting/pagination

Time:03-27

I want to add Skeleton effect to a MUI table. The only requirement for the table is sorting and pagination features. I added loading hook and fake data fetching with 3 seconds delay in order to test, but it doesn't seem possible with DataGrid.

import { useState, useEffect } from 'react';
import type { NextPage } from 'next';
import Container from '@mui/material/Container';
import Box from '@mui/material/Box';
import { DataGrid, GridColDef } from '@mui/x-data-grid';
import { Paper } from '@mui/material';

const columns: GridColDef[] = [
  { field: 'id', headerName: 'ID' },
  { field: 'title', headerName: 'Title', width: 300 },
  { field: 'body', headerName: 'Body', width: 600 },
];

const Home: NextPage = () => {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(true);

  // fetch data from fake API
  useEffect(() => {
    setInterval(
      () =>
        fetch('https://jsonplaceholder.typicode.com/posts')
          .then((response) => response.json())
          .then((data) => {
            setPosts(data);
            setLoading(false);
          }),
      3000
    );
  }, []);

  return (
    <Container maxWidth="lg">
      <Box
        sx={{
          my: 4,
          display: 'flex',
          flexDirection: 'column',
          justifyContent: 'center',
          alignItems: 'center',
        }}
      >
        <Paper sx={{ width: '100%' }}>
          <DataGrid
            rows={posts}
            columns={columns}
            pageSize={10}
            autoHeight
            rowsPerPageOptions={[10]}
            disableSelectionOnClick
            disableColumnMenu
            disableColumnSelector
          />
        </Paper>
      </Box>
    </Container>
  );
};

export default Home;

CodePudding user response:

Mui DataGrid have some custom options to use for loading which you can find at https://mui.com/components/data-grid/components/#loading-overlay , in all if you want to set a custom loading component your DataGrid component will look like

    // You can find a proper height for the Paper component (if you do that 
    // you will need to remove autoHeight from data grid) , or change the data grid height  . 
    // if not the table height wont fit and you will need to edit some styles .

     <Paper sx={{ width: "100%" , height: "600px" }}> 
           <DataGrid
            rows={posts}
            columns={columns}
            pageSize={10}
            // autoHeight
            // sx={{minHeight: 600}}  if you want to use autoHeight you will need add some height
            rowsPerPageOptions={[10]}
            disableSelectionOnClick
            disableColumnMenu
            disableColumnSelector
            components={{
              LoadingOverlay: LoadingSkeleton  
            }}
            loading={loading}   // you need to set your boolean loading
          />
    </Paper>

you can make your custom component with Skeleton

  const LoadingSkeleton = () => (
          <Skeleton variant="rectangular" sx={{ my: 4, mx: 1 }} />
 );

also if you to make a list of rowing skeletons

const LoadingSkeleton = () => (
  <Box
    sx={{
      height: "max-content"
    }}
  >
    {[...Array(10)].map((_) => (
      <Skeleton variant="rectangular" sx={{ my: 4, mx: 1 }} />
    ))}
  </Box>
);

a simple example can be found here https://codesandbox.io/s/trusting-rgb-wwqd2o?file=/src/App.js:440-644 , the list of rowing skeletons might needs some changes in styling .

CodePudding user response:

  1. You need to import Skeleton component from MUI.

  2. Use the component in your JSX code. Whenever loading === true you need to show the Skeleton component. Example:


{loading ? 
 <Skeleton variant="rectangular" width={210} height={118} />
 :
 <>
  ...Your table...
 </>
}

  1. Whenver the request is recalled you need to call setLoading(true) so you can show the user that a request is made and some data is loading.

  2. I suggest moving the setLoading() function into .then() block [!] That way even if the request fails the loading will stop and you can show some kind of error message. In your case if the requests fails the loading will keep on until you reload the page or call the request until it succeeds. [!]

  • Related