-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DataGrid] Make possible to memoize rows and cells (#7846)
Signed-off-by: Matheus Wichman <[email protected]> Co-authored-by: Andrew Cherniavskii <[email protected]>
- Loading branch information
1 parent
17dd6eb
commit 13c7b10
Showing
41 changed files
with
1,010 additions
and
446 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import * as React from 'react'; | ||
import Box from '@mui/material/Box'; | ||
import { teal } from '@mui/material/colors'; | ||
import { unstable_useForkRef as useForkRef } from '@mui/utils'; | ||
import { DataGridPro, GridRow, GridColumnHeaders } from '@mui/x-data-grid-pro'; | ||
import { useDemoData } from '@mui/x-data-grid-generator'; | ||
|
||
const TraceUpdates = React.forwardRef((props, ref) => { | ||
const { Component, ...other } = props; | ||
const rootRef = React.useRef(); | ||
const handleRef = useForkRef(rootRef, ref); | ||
|
||
React.useEffect(() => { | ||
rootRef.current?.classList.add('updating'); | ||
|
||
const timer = setTimeout(() => { | ||
rootRef.current?.classList.remove('updating'); | ||
}, 500); | ||
|
||
return () => clearTimeout(timer); | ||
}); | ||
|
||
return <Component ref={handleRef} {...other} />; | ||
}); | ||
|
||
const RowWithTracer = React.forwardRef((props, ref) => { | ||
return <TraceUpdates ref={ref} Component={GridRow} {...props} />; | ||
}); | ||
|
||
const ColumnHeadersWithTracer = React.forwardRef((props, ref) => { | ||
return <TraceUpdates ref={ref} Component={GridColumnHeaders} {...props} />; | ||
}); | ||
|
||
const MemoizedRow = React.memo(RowWithTracer); | ||
const MemoizedColumnHeaders = React.memo(ColumnHeadersWithTracer); | ||
|
||
export default function GridWithReactMemo() { | ||
const { data } = useDemoData({ | ||
dataSet: 'Commodity', | ||
rowLength: 100, | ||
editable: true, | ||
maxColumns: 15, | ||
}); | ||
|
||
return ( | ||
<Box | ||
sx={{ | ||
height: 400, | ||
width: '100%', | ||
'&&& .updating': (theme) => ({ | ||
background: teal[theme.palette.mode === 'dark' ? 900 : 100], | ||
transition: theme.transitions.create('background', { | ||
duration: theme.transitions.duration.standard, | ||
}), | ||
}), | ||
}} | ||
> | ||
<DataGridPro | ||
{...data} | ||
rowHeight={38} | ||
checkboxSelection | ||
disableRowSelectionOnClick | ||
slots={{ | ||
row: MemoizedRow, | ||
columnHeaders: MemoizedColumnHeaders, | ||
}} | ||
/> | ||
</Box> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import * as React from 'react'; | ||
import Box from '@mui/material/Box'; | ||
import { teal } from '@mui/material/colors'; | ||
import { unstable_useForkRef as useForkRef } from '@mui/utils'; | ||
import { DataGridPro, GridRow, GridColumnHeaders } from '@mui/x-data-grid-pro'; | ||
import { useDemoData } from '@mui/x-data-grid-generator'; | ||
|
||
const TraceUpdates = React.forwardRef<any, any>((props, ref) => { | ||
const { Component, ...other } = props; | ||
const rootRef = React.useRef<HTMLElement>(); | ||
const handleRef = useForkRef(rootRef, ref); | ||
|
||
React.useEffect(() => { | ||
rootRef.current?.classList.add('updating'); | ||
|
||
const timer = setTimeout(() => { | ||
rootRef.current?.classList.remove('updating'); | ||
}, 500); | ||
|
||
return () => clearTimeout(timer); | ||
}); | ||
|
||
return <Component ref={handleRef} {...other} />; | ||
}); | ||
|
||
const RowWithTracer = React.forwardRef((props, ref) => { | ||
return <TraceUpdates ref={ref} Component={GridRow} {...props} />; | ||
}); | ||
|
||
const ColumnHeadersWithTracer = React.forwardRef((props, ref) => { | ||
return <TraceUpdates ref={ref} Component={GridColumnHeaders} {...props} />; | ||
}); | ||
|
||
const MemoizedRow = React.memo(RowWithTracer); | ||
const MemoizedColumnHeaders = React.memo(ColumnHeadersWithTracer); | ||
|
||
export default function GridWithReactMemo() { | ||
const { data } = useDemoData({ | ||
dataSet: 'Commodity', | ||
rowLength: 100, | ||
editable: true, | ||
maxColumns: 15, | ||
}); | ||
|
||
return ( | ||
<Box | ||
sx={{ | ||
height: 400, | ||
width: '100%', | ||
'&&& .updating': (theme) => ({ | ||
background: teal[theme.palette.mode === 'dark' ? 900 : 100], | ||
transition: theme.transitions.create('background', { | ||
duration: theme.transitions.duration.standard, | ||
}), | ||
}), | ||
}} | ||
> | ||
<DataGridPro | ||
{...data} | ||
rowHeight={38} | ||
checkboxSelection | ||
disableRowSelectionOnClick | ||
slots={{ | ||
row: MemoizedRow, | ||
columnHeaders: MemoizedColumnHeaders, | ||
}} | ||
/> | ||
</Box> | ||
); | ||
} |
10 changes: 10 additions & 0 deletions
10
docs/data/data-grid/performance/GridWithReactMemo.tsx.preview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<DataGridPro | ||
{...data} | ||
rowHeight={38} | ||
checkboxSelection | ||
disableRowSelectionOnClick | ||
slots={{ | ||
row: MemoizedRow, | ||
columnHeaders: MemoizedColumnHeaders, | ||
}} | ||
/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Data Grid - Performance | ||
|
||
<p class="description">Improve the performance of the DataGrid using the recommendations from this guide.</p> | ||
|
||
## Memoize inner components with `React.memo` | ||
|
||
The `DataGrid` component is composed of a central state object where all data is stored. | ||
When an API method is called, a prop changes, or the user interacts with the UI (e.g. filtering a column), this state object is updated with the changes made. | ||
To reflect the changes in the interface, the component must re-render. | ||
Since the state behaves like `React.useState`, the `DataGrid` component will re-render its children, including column headers, rows, and cells. | ||
With smaller datasets, this is not a problem for concern, but it can become a bottleneck if the number of rows increases, especially if many columns render [custom content](/x/react-data-grid/column-definition/#rendering-cells). | ||
One way to overcome this issue is using `React.memo` to only re-render the child components when their props have changed. | ||
To start using memoization, import the inner components, then pass their memoized version to the respective slots, as follow: | ||
|
||
```tsx | ||
import { | ||
GridRow, | ||
GridColumnHeaders, | ||
DataGrid, // or DataGridPro, DataGridPremium | ||
} from '@mui/x-data-grid'; | ||
|
||
const MemoizedRow = React.memo(GridRow); | ||
const MemoizedColumnHeaders = React.memo(GridColumnHeaders); | ||
|
||
<DataGrid | ||
slots={{ | ||
row: MemoizedRow, | ||
columnHeaders: MemoizedColumnHeaders, | ||
}} | ||
/>; | ||
``` | ||
|
||
The following demo show this trick in action. | ||
It also contains additional logic to highlight the components when they re-render. | ||
|
||
{{"demo": "GridWithReactMemo.js", "bg": "inline", "defaultCodeOpen": false}} | ||
|
||
:::warning | ||
We do not ship the components above already wrapped with `React.memo` because if you have rows whose cells display custom content not derived from the received props, e.g. selectors, these cells may display outdated information. | ||
If you define a column with a custom cell renderer where content comes from a [selector](/x/react-data-grid/state/#catalog-of-selectors) that changes more often than the props passed to `GridRow`, the row component should not be memoized. | ||
::: | ||
|
||
## API | ||
|
||
- [DataGrid](/x/api/data-grid/data-grid/) | ||
- [DataGridPro](/x/api/data-grid/data-grid-pro/) | ||
- [DataGridPremium](/x/api/data-grid/data-grid-premium/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import * as React from 'react'; | ||
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; | ||
import * as pageProps from 'docsx/data/data-grid/performance/performance.md?@mui/markdown'; | ||
|
||
export default function Page() { | ||
return <MarkdownDocs {...pageProps} />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.