Infinite loop caused by selectableRowSelected + onSelectedRowsChange
Describe the bug
I'm experiencing a strange and fatal behavior when using selectableRowSelected in combination with onSelectedRowsChange: The two props works great on their own, but broke everything when used together: (in order to pre-select and then select new rows), i run into an infinite loop (re-render) as soon as the table loads.
Based on my debugging, the fault occurs when i update the independent state which is keeping the rows selected. The strange things, is that the state is never used in the application (neither i have a useEffect hook), but the behavior of the table changes based on how i update the state.;
- If i update the state with the selectedRows provided by onSelectedRowsChange-> Infinte loop (Max update depth excedeed)
- If i update the state with an empty array (via onSelectedRowsChange trigger) -> Infinte loop (Max update depth excedeed);
- If i update the state with any string (via onSelectedRowsChange trigger) -> No errors and the selection work as expected (but i am unable to get the selected rows);
- If i update the state by strinigify the selectedRows provided by onSelectedRowsChange -> No infinite loop, but i am unable to select new rows, the state keep only the stringified selected rows defined by selectableRowSelected;
To Reproduce
https://codesandbox.io/p/sandbox/throbbing-currying-gy9x78
import React, { useState, useEffect } from 'react';
import DataTable from "react-data-table-component";
const SampleDataTable = () => {
const data = [
{ id: 1, name: "John Doe", age: 28, profession: "Engineer" },
{ id: 2, name: "Jane Smith", age: 32, profession: "Designer" },
{ id: 3, name: "Bob Johnson", age: 45, profession: "Manager" },
];
const columns = [
{ name: "ID", selector: "id", sortable: true },
{ name: "Name", selector: "name", sortable: true },
{ name: "Age", selector: "age", sortable: true },
{ name: "Profession", selector: "profession", sortable: true },
];
const [selectedItems, setSelectedItems] = useState([]);
const handleSelectedRowsChange = ({ selectedRows }) => {
setSelectedItems(selectedRows);
};
const defaultSelectedRows = (row) => row.id > 2;
return (
<div>
<h2>Sample Data Table {selectedItems.length}</h2>
<DataTable
columns={columns}
data={data}
selectableRows={true}
selectableRowsHighlight
pagination
highlightOnHover
onSelectedRowsChange={handleSelectedRowsChange}
selectableRowSelected={defaultSelectedRows}
/>
</div>
);
};
export default SampleDataTable;
Describe the bug
I'm experiencing a strange and fatal behavior when using selectableRowSelected in combination with onSelectedRowsChange: The two props works great on their own, but broke everything when used together: (in order to pre-select and then select new rows), i run into an infinite loop (re-render) as soon as the table loads.
Based on my debugging, the fault occurs when i update the independent state which is keeping the rows selected. The strange things, is that the state is never used in the application (neither i have a useEffect hook), but the behavior of the table changes based on how i update the state.;
- If i update the state with the selectedRows provided by onSelectedRowsChange-> Infinte loop (Max update depth excedeed)
- If i update the state with an empty array (via onSelectedRowsChange trigger) -> Infinte loop (Max update depth excedeed);
- If i update the state with any string (via onSelectedRowsChange trigger) -> No errors and the selection work as expected (but i am unable to get the selected rows);
- If i update the state by strinigify the selectedRows provided by onSelectedRowsChange -> No infinite loop, but i am unable to select new rows, the state keep only the stringified selected rows defined by selectableRowSelected;
To Reproduce
https://codesandbox.io/p/sandbox/throbbing-currying-gy9x78
import React, { useState, useEffect } from 'react'; import DataTable from "react-data-table-component"; const SampleDataTable = () => { const data = [ { id: 1, name: "John Doe", age: 28, profession: "Engineer" }, { id: 2, name: "Jane Smith", age: 32, profession: "Designer" }, { id: 3, name: "Bob Johnson", age: 45, profession: "Manager" }, ]; const columns = [ { name: "ID", selector: "id", sortable: true }, { name: "Name", selector: "name", sortable: true }, { name: "Age", selector: "age", sortable: true }, { name: "Profession", selector: "profession", sortable: true }, ]; const [selectedItems, setSelectedItems] = useState([]); const handleSelectedRowsChange = ({ selectedRows }) => { setSelectedItems(selectedRows); }; const defaultSelectedRows = (row) => row.id > 2; return ( <div> <h2>Sample Data Table {selectedItems.length}</h2> <DataTable columns={columns} data={data} selectableRows={true} selectableRowsHighlight pagination highlightOnHover onSelectedRowsChange={handleSelectedRowsChange} selectableRowSelected={defaultSelectedRows} /> </div> ); }; export default SampleDataTable;
the problem is that the selectedRows is an Array, so the ref of selectedRows would be updated every time by setting through setSelectedItems even though the elements of selectedRows are not changed. so you should use function parameter of setState
you can check my solution