gregnb / gregnb/mui-datatables

Optimizing Performance with customBodyRender

Open
#1,443 9 comments 1 reaction 0 assignees View on GitHub
help wanted
Dominant language
JavaScript
Stars
2.7k
Forks
906
PR merge metrics
No merged PRs in 30d

Description

Hi,

I have a relatively simple use case. But am finding mui-datatables to be non-performant as my data set grows (up to just 100 records). I'm guessing it's because I use a customBodyRender on each of 5 columns...and it seems that function is being run for all fields in all rows even when just one row is updated. Let me try and explain:

1. I have an array of objects in a redux store. Each object looks like this:
`{inbound:false, id:-1,message: [0x90,0x3c,0x64], delta:1, timestamp: new Date() }`
2. This array is appended to (perhaps a few times per second) by a socket.io middleware-->reducer. It's size, however, is limited to just 100 entries.
`state.midi.history = [newPayload].concat(state.midi.history).slice(0,ITEM_HISTORY_LIMIT);`
3. In my mui-datatable component, I subscribe to the relevant redux state in mapStateToProps.
`const mapStateToProps = (state, ownProps) => {
return { midi: state.midi};
};`
4. ...and feed it to the mui-datable:
``
5. My mui-datatable has 5 columns - but because my source data is "raw", 3 of them require (I think) **customBodyRenders**. Example:

- **timestamp**. the source data is a date object. inside customBodyRender, I run the value through a helper function that returns a string.

- **message**. the source data is an array of bytes. I run the array through a helper function that returns a prettified string marked up with colors.

- **translation**. there is no translation field in the source object. I lookup the message byte array (see above), and run it through a helper function that returns a marked up Fragment.
`let msg = tableMeta.rowData[_.findIndex(Columns, { name: "message" })];`
`let map = MCUMap(msg);`
...
...
```return (

{abbr}
{map.target ? out : msg.toString()}

);
```
It all works. BUT as the array of objects grows, even to just 50, the fact seems to be that the table is re-calculating every field in every row and it gets slow. I thought, in react, one could/should use a key on list/table data so that only rows with a new key got updated. Not the 99 rows that didn't change. But that paradigm doesn't seem to exist here.

Of course, it could just be that my approach is all wrong -- and so would appreciate advice. I love the searching and filtering and general ease of use of mui-datatables -- so would love to get this fixed!

Here's a pic of the resultant table:
![Capture](https://user-images.githubusercontent.com/2557753/88567287-4a688880-d005-11ea-9c6b-540c90f0826a.JPG)

Thanks.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start from the MUIDataTable component, its five customBodyRender callbacks, and the Redux history update path described in the issue. Profile rerenders while new socket.io data is appended, then establish which rows and callbacks are recalculated and document a measurable performance target as the definition of done.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react, redux
Domain
frontend, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.