Reducer in useRowSelect relies on external state
See original GitHub issuePulled out of #2120, because this should be fixed even if 2120 is solved in another way or ends up being unrelated.
Describe the bug
The handler of toggleRowSelected
action type reads isSelected
from row objects:
As a result, when multiple selection changes happen within the same reducer run, toggleRowSelected
uses the initial row selection state, regardless of whether another action updated it earlier in the same run.
Provide an example via Codesandbox!
Sorry I did not make one. The idea is just to do this:
assert(someRow.isSelected); // the bug shows only if row is selected
toggleAllRowsSelected(false) ;
someRow.toggleRowSelected(true);
What happens then is this:
- The reducer handles
toggleAllRowsSelected
.- It clears selectedRowIds.
- At this point, the
isSelected
property of rows has not been updated.
- The reducer handles
toggleRowSelected
.- It sees it should select the row.
- It looks at
row.isSelected
. It is true, because react did not yet recompute it. - It skips the update.
- Therefore the row is not added back to
selectedRowIds
.
- At last, react recomputes
selectedFlatRows
, which updatesisSelected
as a side effect (see #2170).
It is hard to make a minimal example, because this triggers observable bugs depending on when exactly React chooses to recompute selectedFlatRows
, which is further obfuscated by #2170.
Expected behavior
Reducers should never access any information outside of previousState
. Otherwise they no longer are predictable.
Replacing row.isSelected
by id in state.selectedRowIds
or something similar should work I believe.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:12
- Comments:5
+1 to add some noise. I spent a couple hours integrating/debugging inconsistency bugs before finding this issue and tossing out the code to roll our own implementation. The design/spec looks great so I’m hopeful it’s more stable in v8 🤞
@fparga a workaround is to
selectedRowIds
directly, ignoring helper methods andisSelected
attribute. It is an annoyance, but at least you can use all other parts of react-table normally.Looking forward to v8 though 😃