Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Rework useGridRows high frequency update #2561

Merged
merged 27 commits into from
Sep 27, 2021
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5661b81
[core] Rework useGridRows high frequency update
flaviendelangle Sep 7, 2021
84afae2
Remove unused event
flaviendelangle Sep 7, 2021
8a37bef
Fix
flaviendelangle Sep 7, 2021
e330b7b
Test should passé
flaviendelangle Sep 7, 2021
e62ddc9
Fix doc
flaviendelangle Sep 7, 2021
200851c
Fix tests
flaviendelangle Sep 7, 2021
9275add
Add tests and docs
flaviendelangle Sep 8, 2021
4c748e4
Merge
flaviendelangle Sep 8, 2021
5bfdc42
Undo useGKN modif
flaviendelangle Sep 8, 2021
f431b64
Merge
flaviendelangle Sep 10, 2021
e1f7749
Update proptypes
flaviendelangle Sep 10, 2021
942cfc8
Make the throttling pro
flaviendelangle Sep 10, 2021
e45684a
Fix
flaviendelangle Sep 10, 2021
3f5e7cc
Fix
flaviendelangle Sep 10, 2021
433c81f
Code review
flaviendelangle Sep 10, 2021
6330755
Merge branch 'next' into rows-throttle
flaviendelangle Sep 13, 2021
8b7d651
Fix
flaviendelangle Sep 13, 2021
e38f9e6
Do not throttle the prop updates
flaviendelangle Sep 13, 2021
943879f
yarn docs:api:build
flaviendelangle Sep 13, 2021
f98f878
proptypes
flaviendelangle Sep 13, 2021
51764d3
Merge branch 'next' into rows-throttle
flaviendelangle Sep 13, 2021
695a133
Code review
flaviendelangle Sep 13, 2021
2972dce
Remove delay docs
flaviendelangle Sep 13, 2021
abea526
Merge branch 'next' into rows-throttle
flaviendelangle Sep 14, 2021
953f1e2
Merge branch 'next' into rows-throttle
flaviendelangle Sep 15, 2021
adb3750
Merge branch 'next' into rows-throttle
flaviendelangle Sep 17, 2021
21d30f3
Merge branch 'next' into rows-throttle
flaviendelangle Sep 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions docs/src/pages/components/data-grid/rows/ThrottledRowsGrid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react';
import { DataGridPro, useGridApiRef } from '@mui/x-data-grid-pro';
import { interval } from 'rxjs';
import { randomInt, randomUserName } from '@mui/x-data-grid-generator';

const columns = [
{ field: 'id' },
{ field: 'username', width: 150 },
{ field: 'age', width: 80, type: 'number' },
];

const rows = [
{ id: 1, username: randomUserName(), age: randomInt(10, 80) },
{ id: 2, username: randomUserName(), age: randomInt(10, 80) },
{ id: 3, username: randomUserName(), age: randomInt(10, 80) },
{ id: 4, username: randomUserName(), age: randomInt(10, 80) },
];

export default function ApiRefRowsGrid() {
const apiRef = useGridApiRef();

React.useEffect(() => {
const subscription = interval(10).subscribe(() => {
apiRef.current.updateRows([
{
id: randomInt(1, 4),
username: randomUserName(),
age: randomInt(10, 80),
},
{
id: randomInt(1, 4),
username: randomUserName(),
age: randomInt(10, 80),
},
]);
});

return () => {
subscription.unsubscribe();
};
}, [apiRef]);

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
rows={rows}
columns={columns}
apiRef={apiRef}
throttleRowsMs={500}
/>
</div>
);
}
53 changes: 53 additions & 0 deletions docs/src/pages/components/data-grid/rows/ThrottledRowsGrid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react';
import { DataGridPro, useGridApiRef } from '@mui/x-data-grid-pro';
import { interval } from 'rxjs';
import { randomInt, randomUserName } from '@mui/x-data-grid-generator';

const columns = [
{ field: 'id' },
{ field: 'username', width: 150 },
{ field: 'age', width: 80, type: 'number' },
];

const rows = [
{ id: 1, username: randomUserName(), age: randomInt(10, 80) },
{ id: 2, username: randomUserName(), age: randomInt(10, 80) },
{ id: 3, username: randomUserName(), age: randomInt(10, 80) },
{ id: 4, username: randomUserName(), age: randomInt(10, 80) },
];

export default function ApiRefRowsGrid() {
flaviendelangle marked this conversation as resolved.
Show resolved Hide resolved
const apiRef = useGridApiRef();

React.useEffect(() => {
const subscription = interval(10).subscribe(() => {
apiRef.current.updateRows([
{
id: randomInt(1, 4),
username: randomUserName(),
age: randomInt(10, 80),
},
{
id: randomInt(1, 4),
username: randomUserName(),
age: randomInt(10, 80),
},
]);
});

return () => {
subscription.unsubscribe();
};
}, [apiRef]);

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
rows={rows}
columns={columns}
apiRef={apiRef}
throttleRowsMs={500}
/>
</div>
);
}
9 changes: 9 additions & 0 deletions docs/src/pages/components/data-grid/rows/rows.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ Alternatively, if you would like to delete a row, you would need to pass an extr
apiRef.current.updateRows([{ id: 1, _action: 'delete' }]);
```

### Throttling grid update [<span class="pro"></span>](https://material-ui.com/store/items/material-ui-pro/)
flaviendelangle marked this conversation as resolved.
Show resolved Hide resolved

If you have high frequency updates, but you want to keep good performances, you can pass set the `throttleRowsMs` prop to define the maximum update frequency.
flaviendelangle marked this conversation as resolved.
Show resolved Hide resolved
When receiving updates more frequent than this threshold, the Grid will wait before applying the new values to avoid triggering heavy work too many times.
flaviendelangle marked this conversation as resolved.
Show resolved Hide resolved

The following demo updates the rows every 10ms but only apply them to the Grid every 500ms.
flaviendelangle marked this conversation as resolved.
Show resolved Hide resolved

{{"demo": "pages/components/data-grid/rows/ThrottledRowsGrid.js", "bg": "inline"}}

## Row height

By default, the rows have a height of 52 pixels.
Expand Down
12 changes: 0 additions & 12 deletions packages/grid/_modules_/grid/constants/eventsConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,23 +281,11 @@ export enum GridEvents {
* Fired when the user ends reordering a column.
*/
columnOrderChange = 'columnOrderChange',
/**
* Fired when some of the rows are updated.
* @ignore - do not document.
*/
rowsUpdate = 'rowsUpdate',
/**
* Fired when all the rows are updated.
* @ignore - do not document.
*/
rowsSet = 'rowsSet',
/**
* Implementation detail.
* Fired to reset the sortedRow when the set of rows changes.
* It's important as the rendered rows are coming from the sortedRow
* @ignore - do not document.
*/
rowsClear = 'rowsClear',
/**
* Fired when the columns state is changed.
* Called with an array of strings corresponding to the field names.
Expand Down
4 changes: 2 additions & 2 deletions packages/grid/_modules_/grid/hooks/features/core/gridState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
} from '../filter/visibleGridRowsState';
import { GridFocusState, GridTabIndexState } from '../focus/gridFocusState';
import { GridPreferencePanelState } from '../preferencesPanel/gridPreferencePanelState';
import { getInitialGridRowState, InternalGridRowsState } from '../rows/gridRowsState';
import { getInitialGridRowState, GridRowsState } from '../rows/gridRowsState';
import { GridSelectionModel } from '../../../models/gridSelectionModel';
import { getInitialGridSortingState, GridSortingState } from '../sorting/gridSortingState';
import {
Expand All @@ -33,7 +33,7 @@ import {
import { getInitialPaginationState, GridPaginationState } from '../pagination/gridPaginationState';

export interface GridState {
rows: InternalGridRowsState;
rows: GridRowsState;
editRows: GridEditRowsModel;
pagination: GridPaginationState;
columns: GridColumnsState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,5 @@ export const useGridFilter = (
}, [apiRef, logger, props.filterModel, setGridState]);

useGridApiEventHandler(apiRef, GridEvents.rowsSet, apiRef.current.applyFilters);
useGridApiEventHandler(apiRef, GridEvents.rowsUpdate, apiRef.current.applyFilters);
useGridApiEventHandler(apiRef, GridEvents.columnsChange, onColUpdated);
};
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { createSelector } from 'reselect';
import { GridRowId, GridRowModel } from '../../../models/gridRows';
import { GridState } from '../core/gridState';
import { InternalGridRowsState } from './gridRowsState';
import { GridRowsState } from './gridRowsState';

export type GridRowsLookup = Record<GridRowId, GridRowModel>;

export const gridRowsStateSelector = (state: GridState) => state.rows;

export const gridRowCountSelector = createSelector(
gridRowsStateSelector,
(rows: InternalGridRowsState) => rows && rows.totalRowCount,
(rows: GridRowsState) => rows.totalRowCount,
);

export const gridRowsLookupSelector = createSelector(
gridRowsStateSelector,
(rows: InternalGridRowsState) => rows && rows.idRowsLookup,
(rows: GridRowsState) => rows.idRowsLookup,
);

export const unorderedGridRowIdsSelector = createSelector(
gridRowsStateSelector,
(rows: InternalGridRowsState) => rows.allRows,
(rows: GridRowsState) => rows.allRows,
);

export const unorderedGridRowModelsSelector = createSelector(
gridRowsStateSelector,
(rows: InternalGridRowsState) => rows.allRows.map((id) => rows.idRowsLookup[id]),
(rows: GridRowsState) => rows.allRows.map((id) => rows.idRowsLookup[id]),
);
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { GridRowId, GridRowModel } from '../../../models/gridRows';

export interface InternalGridRowsState {
export interface GridRowsState {
idRowsLookup: Record<GridRowId, GridRowModel>;
allRows: GridRowId[];
totalRowCount: number;
}

export const getInitialGridRowState: () => InternalGridRowsState = () => ({
export interface GridRowsInternalCache {
flaviendelangle marked this conversation as resolved.
Show resolved Hide resolved
state: GridRowsState;
timeout: NodeJS.Timeout | null;
lastUpdateMs: number | null;
}

export const getInitialGridRowState: () => GridRowsState = () => ({
idRowsLookup: {},
allRows: [],
totalRowCount: 0,
Expand Down
Loading