'React-table: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate
I am using React-table for one of my projects. I implemented the row selection as mentioned in the docs.
below is my table.js
import React, { useEffect, useMemo } from 'react'
import { useTable, usePagination, useRowSelect } from 'react-table';
import {Button, Dropdown, DropdownButton, Form} from 'react-bootstrap';
import BTable from 'react-bootstrap/Table';
export function Table({ columns, data, fetchData, noDataMessage, pageCount: controlledPageCount, loading, rowSelectionEnabled, getSelectedRows }) {
const memoizedColumns = useMemo(() => columns, [columns]);
const memoizedData = useMemo(() => data, [data]);
// Use the state and functions returned from useTable to build your UI
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
selectedFlatRows,
isAllRowsSelected,
state: { pageIndex, pageSize, selectedRowIds },
} = useTable({
columns: memoizedColumns,
data: memoizedData,
noDataMessage,
initialState: { pageIndex: 0, pageSize: 15 },
manualPagination: true,
pageCount: controlledPageCount,
},usePagination, useRowSelect,
hooks => {
rowSelectionEnabled && hooks.visibleColumns.push(columns => [
// Let's make a column for selection
{
id: 'selection',
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
),
},
...columns,
])
}
)
const setSize = (selectedVal) => {
setPageSize(selectedVal);
}
// const fetchDataDebounced = useAsyncDebounce(fetchData, 100);
React.useEffect(() => {
data.length > 0 && fetchData && fetchData({ pageIndex, pageSize })
}, [fetchData, pageIndex, pageSize])
// React.useEffect(() => {
// data.length === 0 && gotoPage(0)
// }, [data])
// Render the UI for your table
return (
<>
<BTable striped bordered loading={true} minRows={0} className='border-radius-important' {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps()}>{column.render('Header')}</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.length > 0 ? (page.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})) : <tr style={{height: '350px'}}><td colSpan={10} style={{verticalAlign: 'middle'}}><NoDataComponent message={noDataMessage}/></td></tr>}
</tbody>
</BTable>
{ pageCount > 1 ? (<div className="pagination">
<div style={{width: '100%', paddingTop: '15px'}}>
<div style={{display: 'flex', float: 'right'}}>
<div style={{display: 'block'}}>
<div>
<Button variant='outline-primary' onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
{'<<'}
</Button>{' '}
<Button variant='outline-primary' onClick={() => previousPage()} disabled={!canPreviousPage}>
{'<'}
</Button>{' '}
<Button variant='outline-primary' onClick={() => nextPage()} disabled={!canNextPage}>
{'>'}
</Button>{' '}
<Button variant='outline-primary' onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
{'>>'}
</Button>{' '}
</div>
<div>
Page{' '}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{' '}
</div>
</div>
{/* <div>
| Go to page:{' '}
<input
type="number"
defaultValue={pageIndex + 1}
onChange={e => {
const page = e.target.value ? Number(e.target.value) - 1 : 0
gotoPage(page)
}}
style={{ width: '100px' }}
/>
</div>{' '} */}
</div>
<DropdownButton
style={{float: 'left'}}
title={pageSize}
onSelect={setSize}
>
{[10, 20, 30, 40, 50].map(pageSize => (
<Dropdown.Item eventKey={pageSize}>
{pageSize}
</Dropdown.Item>
))}
</DropdownButton>
</div>
</div>) : null }
{getSelectedRows && getSelectedRows(selectedRowIds, selectedFlatRows, isAllRowsSelected)}
</>
)
}
const NoDataComponent = props => (
// <NoData noDataTitle="This is the dynamic title" {...props} />
<div style={{width: '100%', height: '100%', textAlign: 'center', fontWeight: '700', fontSize: 'large'}}>{props.message}</div>
);
const IndeterminateCheckbox = React.forwardRef(
({ indeterminate, ...rest }, ref) => {
const defaultRef = React.useRef()
const resolvedRef = ref || defaultRef
React.useEffect(() => {
resolvedRef.current.indeterminate = indeterminate
}, [resolvedRef, indeterminate])
return (
<>
<Form.Check type="checkbox" ref={resolvedRef} {...rest} />
</>
)
}
)
and the following is the code where i am using this table
getSelectedRows = (rowIds, rowData, isAllRowsSelected) => {
this.setState({selectedData: rowData});
}
<Table columns={this.state.columns} data={this.state.data} rowSelectionEnabled={true} noDataMessage='There is no data to display' getSelectedRows={this.getSelectedRows} fetchData={this.fetchData} pageCount={this.state.count}></Table>
So whenever the checkbox is selected, following line gets triggered in table.js:
{getSelectedRows && getSelectedRows(selectedRowIds, selectedFlatRows, isAllRowsSelected)}
and getSelectedRows function gets called in my component.
But after that page crashes with the error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate
I read somewhere that memoizing data and columns will fix the issue as it is going into loop rendering again and again. So I memoized data and columns at the start of table.js file. But still the issue is there.
Can someone please help on this. Thanks in advance!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
