Datatable: onRowSelect and onRowUnselect callbacks inconsistent when clicking checkbox in DataTable (v10.9.5)
Describe the bug
After upgrading PrimeReact from version 8.7.3 to 10.9.5, I encountered a bug with the onRowSelect and onRowUnselect properties on the DataTable.
When testing the new version, existing code began to fail when the selection callbacks were triggered via checkbox clicks. However, the same code works correctly when selecting rows by clicking directly on the row itself.
After some investigation, it seems that the callback reference passed as a prop to the DataTable is inconsistent. Specifically:
- When clicking on a row, the callback reference is correctly updated and invoked as expected.
- When clicking on a checkbox, the callback seems to retain the initial reference and does not reflect updates.
This inconsistency causes unexpected behavior and breaks previously working code.
Doing more testing, I realized that when passing the prop onSelectionChange and selection, the functionality of both previous props seems to work as intended.
Code
import { useState } from 'react';
import { Column } from 'primereact/column';
import { DataTable } from 'primereact/datatable';
import 'primereact/resources/themes/lara-light-indigo/theme.css'; //theme
import 'primeicons/primeicons.css'; //icons
import 'primeflex/primeflex.css'; // flex
import './App.css';
const value = [
{
key: '0',
data: {
id: 'Click me',
},
},
{
key: '1',
data: {
id: 'Click me',
},
},
];
function App() {
const [counter, setCounter] = useState(0);
console.log('counter', counter);
return (
Click a row to increase the number
Number of clicks: {counter}
<DataTable
value={value}
onRowSelect={() => {
setCounter(counter + 1);
}}
>
<Column selectionMode="multiple" />
<Column field="data.id" header="wadwa" />
</DataTable>
Click the checkbox to see the error
);
}
export default App;
Reproducer
https://stackblitz.com/edit/vitejs-vite-aotetcgn?file=src%2FApp.tsx
System Information
System:
OS: Linux 5.0 undefined
CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 0 Bytes / 0 Bytes
Shell: 1.0 - /bin/jsh
Binaries:
Node: 20.19.1 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 10.8.2 - /usr/local/bin/npm
pnpm: 8.15.6 - /usr/local/bin/pnpm
npmPackages:
primereact: 10.9.5 => 10.9.5
Steps to reproduce the behavior
- Click anywhere on a row in the DataTable.
- Observe that the counter updates correctly with a new value.
- Now click the checkbox of any row instead.
- The counter resets to its initial value, instead of updating as expected.
Expected behavior
When pressing the checkbox, the invoked callback function should use the updated reference, not the initial one. In the demo, the counter should increment correctly in both cases — clicking the row or the checkbox.
Thank you for the detailed description, it makes the debugging easier and faster.
Replacing the following line
setCounter(counter + 1);
By
setCounter(prev => prev + 1);
Should fix the problem. Let us know if it does :)
Thank you for the detailed description, it makes the debugging easier and faster.
Replacing the following line
setCounter(counter + 1);BysetCounter(prev => prev + 1);Should fix the problem. Let us know if it does :)
Thank you for your quick response. Yes, your solution does indeed fix the issue presented in the demo.
However, that solution cannot be applied to many other situations. Since the reference to the function passed as a prop to the table is not properly updated, any other value captured in the function's scope will remain static, therefore, holding the initial values passed to the function.
For a practical case, check the following stackblitz
Your new use case can be solved by embedding the counter into the row data as in: https://stackblitz.com/edit/vitejs-vite-g7ie3cac?file=src%2FApp.tsx
It should be solvable as well by setting the new parameter "cellMemo" from v10.9.6 to false. As of right now this parameter does not affect the checkbox cells though, only the table body cells. I will create PR to fix that. Be advised though that using this future option will result in performance issues for large datasets.