Skip to content

Commit

Permalink
[DataGridPro] Server side data source lazy loading (#13878)
Browse files Browse the repository at this point in the history
Signed-off-by: Armin Mehinovic <[email protected]>
Co-authored-by: Kenan Yusuf <[email protected]>
Co-authored-by: Bilal Shafi <[email protected]>
Co-authored-by: Sycamore <[email protected]>
  • Loading branch information
4 people authored Dec 2, 2024
1 parent 65ca208 commit 659dc5f
Show file tree
Hide file tree
Showing 53 changed files with 2,314 additions and 191 deletions.
2 changes: 1 addition & 1 deletion docs/data/data-grid/events/events.json
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
{
"projects": ["x-data-grid-pro", "x-data-grid-premium"],
"name": "fetchRows",
"description": "Fired when a new batch of rows is requested to be loaded. Called with a GridFetchRowsParams object.",
"description": "Fired when a new batch of rows is requested to be loaded. Called with a GridFetchRowsParams object. Used to trigger <code>onFetchRows</code>.",
"params": "GridFetchRowsParams",
"event": "MuiEvent<{}>",
"componentProp": "onFetchRows"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default function ServerSideDataGridNoCache() {
...initialState,
pagination: {
paginationModel: { pageSize: 10, page: 0 },
rowCount: 0,
},
}),
[initialState],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default function ServerSideDataGridNoCache() {
...initialState,
pagination: {
paginationModel: { pageSize: 10, page: 0 },
rowCount: 0,
},
}),
[initialState],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import * as React from 'react';
import {
DataGridPro,
useGridApiRef,
GridToolbar,
GRID_ROOT_GROUP_ID,
} from '@mui/x-data-grid-pro';
import Checkbox from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
import { useMockServer } from '@mui/x-data-grid-generator';
import Alert from '@mui/material/Alert';
import Button from '@mui/material/Button';
import Snackbar from '@mui/material/Snackbar';

function ErrorSnackbar(props) {
const { onRetry, ...rest } = props;
return (
<Snackbar {...rest}>
<Alert
severity="error"
variant="filled"
sx={{ width: '100%' }}
action={
<Button color="inherit" size="small" onClick={onRetry}>
Retry
</Button>
}
>
Failed to fetch row data
</Alert>
</Snackbar>
);
}

function ServerSideLazyLoadingErrorHandling() {
const apiRef = useGridApiRef();
const [retryParams, setRetryParams] = React.useState(null);
const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false);

const { fetchRows, ...props } = useMockServer(
{ rowLength: 100 },
{ useCursorPagination: false, minDelay: 300, maxDelay: 800 },
shouldRequestsFail,
);

const dataSource = React.useMemo(
() => ({
getRows: async (params) => {
const urlParams = new URLSearchParams({
filterModel: JSON.stringify(params.filterModel),
sortModel: JSON.stringify(params.sortModel),
start: `${params.start}`,
end: `${params.end}`,
});
const getRowsResponse = await fetchRows(
`https://mui.com/x/api/data-grid?${urlParams.toString()}`,
);

// Reset the retryParams when new rows are fetched
setRetryParams(null);
return {
rows: getRowsResponse.rows,
rowCount: getRowsResponse.rowCount,
};
},
}),
[fetchRows],
);

return (
<div style={{ width: '100%' }}>
<FormControlLabel
control={
<Checkbox
checked={shouldRequestsFail}
onChange={(event) => setShouldRequestsFail(event.target.checked)}
/>
}
label="Make the requests fail"
/>
<div style={{ height: 400, position: 'relative' }}>
{retryParams && (
<ErrorSnackbar
open={!!retryParams}
onRetry={() => {
apiRef.current.unstable_dataSource.fetchRows(
GRID_ROOT_GROUP_ID,
retryParams,
);
setRetryParams(null);
}}
/>
)}
<DataGridPro
{...props}
apiRef={apiRef}
unstable_dataSource={dataSource}
unstable_onDataSourceError={(_, params) => setRetryParams(params)}
unstable_dataSourceCache={null}
unstable_lazyLoading
paginationModel={{ page: 0, pageSize: 10 }}
slots={{ toolbar: GridToolbar }}
/>
</div>
</div>
);
}

export default ServerSideLazyLoadingErrorHandling;
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import * as React from 'react';
import {
DataGridPro,
useGridApiRef,
GridToolbar,
GridDataSource,
GridGetRowsParams,
GRID_ROOT_GROUP_ID,
} from '@mui/x-data-grid-pro';
import Checkbox from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
import { useMockServer } from '@mui/x-data-grid-generator';
import Alert from '@mui/material/Alert';
import Button from '@mui/material/Button';
import Snackbar, { SnackbarProps } from '@mui/material/Snackbar';

function ErrorSnackbar(props: SnackbarProps & { onRetry: () => void }) {
const { onRetry, ...rest } = props;
return (
<Snackbar {...rest}>
<Alert
severity="error"
variant="filled"
sx={{ width: '100%' }}
action={
<Button color="inherit" size="small" onClick={onRetry}>
Retry
</Button>
}
>
Failed to fetch row data
</Alert>
</Snackbar>
);
}

function ServerSideLazyLoadingErrorHandling() {
const apiRef = useGridApiRef();
const [retryParams, setRetryParams] = React.useState<GridGetRowsParams | null>(
null,
);
const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false);

const { fetchRows, ...props } = useMockServer(
{ rowLength: 100 },
{ useCursorPagination: false, minDelay: 300, maxDelay: 800 },
shouldRequestsFail,
);

const dataSource: GridDataSource = React.useMemo(
() => ({
getRows: async (params) => {
const urlParams = new URLSearchParams({
filterModel: JSON.stringify(params.filterModel),
sortModel: JSON.stringify(params.sortModel),
start: `${params.start}`,
end: `${params.end}`,
});
const getRowsResponse = await fetchRows(
`https://mui.com/x/api/data-grid?${urlParams.toString()}`,
);

// Reset the retryParams when new rows are fetched
setRetryParams(null);
return {
rows: getRowsResponse.rows,
rowCount: getRowsResponse.rowCount,
};
},
}),
[fetchRows],
);

return (
<div style={{ width: '100%' }}>
<FormControlLabel
control={
<Checkbox
checked={shouldRequestsFail}
onChange={(event) => setShouldRequestsFail(event.target.checked)}
/>
}
label="Make the requests fail"
/>
<div style={{ height: 400, position: 'relative' }}>
{retryParams && (
<ErrorSnackbar
open={!!retryParams}
onRetry={() => {
apiRef.current.unstable_dataSource.fetchRows(
GRID_ROOT_GROUP_ID,
retryParams,
);
setRetryParams(null);
}}
/>
)}
<DataGridPro
{...props}
apiRef={apiRef}
unstable_dataSource={dataSource}
unstable_onDataSourceError={(_, params) => setRetryParams(params)}
unstable_dataSourceCache={null}
unstable_lazyLoading
paginationModel={{ page: 0, pageSize: 10 }}
slots={{ toolbar: GridToolbar }}
/>
</div>
</div>
);
}

export default ServerSideLazyLoadingErrorHandling;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as React from 'react';
import { DataGridPro } from '@mui/x-data-grid-pro';
import { useMockServer } from '@mui/x-data-grid-generator';

function ServerSideLazyLoadingInfinite() {
const { fetchRows, ...props } = useMockServer(
{ rowLength: 100 },
{ useCursorPagination: false, minDelay: 200, maxDelay: 500 },
);

const dataSource = React.useMemo(
() => ({
getRows: async (params) => {
const urlParams = new URLSearchParams({
filterModel: JSON.stringify(params.filterModel),
sortModel: JSON.stringify(params.sortModel),
start: `${params.start}`,
end: `${params.end}`,
});
const getRowsResponse = await fetchRows(
`https://mui.com/x/api/data-grid?${urlParams.toString()}`,
);

return {
rows: getRowsResponse.rows,
};
},
}),
[fetchRows],
);

return (
<div style={{ width: '100%', height: 400 }}>
<DataGridPro
{...props}
unstable_dataSource={dataSource}
unstable_lazyLoading
paginationModel={{ page: 0, pageSize: 15 }}
/>
</div>
);
}

export default ServerSideLazyLoadingInfinite;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from 'react';
import {
DataGridPro,
GridDataSource,
GridGetRowsParams,
} from '@mui/x-data-grid-pro';
import { useMockServer } from '@mui/x-data-grid-generator';

function ServerSideLazyLoadingInfinite() {
const { fetchRows, ...props } = useMockServer(
{ rowLength: 100 },
{ useCursorPagination: false, minDelay: 200, maxDelay: 500 },
);

const dataSource: GridDataSource = React.useMemo(
() => ({
getRows: async (params: GridGetRowsParams) => {
const urlParams = new URLSearchParams({
filterModel: JSON.stringify(params.filterModel),
sortModel: JSON.stringify(params.sortModel),
start: `${params.start}`,
end: `${params.end}`,
});
const getRowsResponse = await fetchRows(
`https://mui.com/x/api/data-grid?${urlParams.toString()}`,
);

return {
rows: getRowsResponse.rows,
};
},
}),
[fetchRows],
);

return (
<div style={{ width: '100%', height: 400 }}>
<DataGridPro
{...props}
unstable_dataSource={dataSource}
unstable_lazyLoading
paginationModel={{ page: 0, pageSize: 15 }}
/>
</div>
);
}

export default ServerSideLazyLoadingInfinite;
Loading

0 comments on commit 659dc5f

Please sign in to comment.