react-data-table-component icon indicating copy to clipboard operation
react-data-table-component copied to clipboard

Infinite loop caused by selectableRowSelected + onSelectedRowsChange

Open budby opened this issue 9 months ago • 1 comments

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;

budby avatar Mar 12 '25 02:03 budby

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

Image

QDFish avatar Jun 26 '25 03:06 QDFish