gregnb / gregnb/mui-datatables
Generating dynamic column definitions fails with too many columns (maximum call stack size exceeded)
- Dominant language
- JavaScript
- Stars
- 2.7k
- Forks
- 906
- PR merge metrics
- No merged PRs in 30d
Description
## Expected Behavior
The ability to change the column definitions in runtime is important, because I often need to pass props to the `options.customBodyRender` function in columns.
I expect this to work by using the columns I pass in the props, and when updating them it should reflect the changes without error.
## Current Behavior
Currently if there are too many columns and the array is rebuilt, mui-datatables internally creates a deep clone of the array (using lodash) which fails with max call stack size exceeded error. It's an infinite loop.
Here is the stack trace:
```
Uncaught RangeError: Maximum call stack size exceeded
at baseClone (index.js:875)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at cloneMap (index.js:1093)
at initCloneByTag (index.js:1372)
at baseClone (index.js:921)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at cloneMap (index.js:1093)
at initCloneByTag (index.js:1372)
at baseClone (index.js:921)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at cloneMap (index.js:1093)
at initCloneByTag (index.js:1372)
at baseClone (index.js:921)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
at arrayEach (index.js:130)
at baseClone (index.js:939)
at eval (index.js:946)
```
## Steps to Reproduce (for bugs)
1. Have multiple columns defined inside your render function, or generated by using a function that takes props and returns column definitions. For me, anything above 11 or 12 columns will trigger the bug, but less than that it works - albeit with a small rendering delay when updating.
2. Attempt to sort using any of the columns
3. Receive exception (above)
## Your Environment
| Tech | Version |
|--------------|---------|
| Material-UI | 4.1.3 |
| MUI-datatables | 2.6.1 |
| React | 16.8.2 |
| browser | brave (Chromium) |
## Example code
```javascript
const Trips = ({ classes, ...props }) => {
/** @type {MUIDataTableColumnDef[]>} */
const tripsColumns = [
{ name: '', label: 'Actions', options: { customBodyRender: (_, meta) => , print: false } },
{ name: 'company', label: 'Company', options: { customBodyRender: v => (e.preventDefault(), e.stopPropagation(), props.handleCompanyChange({ label: v.name, value: v.id, raw: v }))}>{v.name} } },
{ name: 'id', label: 'ID', options: { customBodyRender: v => {v} } },
{ name: 'status', label: 'Status', options: { customBodyRender: v => capitalize(v.replace('_', ' ')) } },
{ name: 'created_by', label: 'Planner', options: { customBodyRender: v => `User #${v}` } },
{ name: 'start_dt', label: 'Start Date', options: { customBodyRender: v => {moment(v).format('MMM DD, YY')} } },
{ name: 'end_dt', label: 'End Date', options: { customBodyRender: v => {moment(v).format('MMM DD, YY')} } },
{ name: 'travelers', label: 'Travelers', options: { customBodyRender: v => smartJoin(v.map(t => firstNameAndLastInitial(t)), 2, '', v.length <= 2 ? ', ' : ' +'), sort: false } },
{ name: 'sent_for_approval', label: 'Sent for Approval', options: { customBodyRender: v => v ? moment(v).format('MMM DD, YY') : '-' } },
{ name: 'approved', label: 'Approved', options: { customBodyRender: v => v ? moment(v).format('MMM DD, YY') : '-' } },
{ name: 'approvers', label: 'Approvers', options: { customBodyRender: v => smartJoin(v.map(t => firstNameAndLastInitial(t)), 2, '', v.length <= 2 ? ', ' : ' +'), sort: false } },
{ name: 'flights_cost', label: Flights $, options: { customBodyRender: v => currency(v) } },
{ name: 'hotels_cost', label: Hotels $, options: { customBodyRender: v => currency(v) } },
{ name: 'surcharges_cost', label: Extras $, options: { customBodyRender: v => currency(v) } },
{ name: 'total_spend', label: Total $, options: { customBodyRender: v => currency(v) } },
];
return (
props.handleCompanyChange(v)} />
props.handleStatusChange(v)} />
props.handleTripSelect(props.trips[meta.rowIndex].id),
onChangePage: page => props.handlePaginationChange({ page: page + 1 }),
onChangeRowsPerPage: page_size => props.handlePaginationChange({ page_size }),
onColumnSortChange: (column, direction) => props.handleSortChange(column, direction),
}} />
);
};
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.