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:
You need to import Skeleton component from MUI.
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...
</>
}
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.
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. [!]