Rows and Cells don't have a stable keys if the row is move to another index
material-react-table version
3.2.1
react & react-dom versions
18.3.1
Describe the bug and the steps to reproduce it
Rows and Cells don't have a stable keys if the row is move to another index. This cause users to lose focus if the row order change.
- Render a table with some data with a cell that has a input field
- Focus on the input
- Reorder the table (programmatically)
Why this Matters
Preserves the input DOM node, keeping focus when rows get reordered.
Minimal, Reproducible Example - (Optional, but Recommended)
https://codesandbox.io/p/sandbox/awesome-chebyshev-lvrv4z
Screenshots or Videos (Optional)
Relevant lines of codes
https://github.com/KevinVandy/material-react-table/blob/8293b961523dc14878bf93af6122c6766e7c2233/packages/material-react-table/src/components/body/MRT_TableBodyRow.tsx#L251
https://github.com/KevinVandy/material-react-table/blob/8293b961523dc14878bf93af6122c6766e7c2233/packages/material-react-table/src/components/body/MRT_TableBody.tsx#L178
Do you intend to try to help solve this bug with your own PR?
Yes, I am also opening a PR that solves the problem along side this issue
Terms
- [x] I understand that if my bug cannot be reliably reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
In React, keys should represent the identity of the underlying data, not its position in the array. Currently, the row and cell keys include row.index / staticRowIndex. This causes React to treat a row as a different element whenever its order changes, even though it’s still the same underlying row.
That leads to issues like:
- DOM nodes being torn down and recreated when rows are reordered.
- Input fields losing focus (as shown in the demo).
- Any stateful components inside the row/cell resetting unnecessarily.
By instead using only a stable row identifier (e.g., row.id, which can come from getRowId), React can correctly preserve the existing DOM nodes when rows move, keeping input focus and local state intact.
So it’s not just “removing info” from the key, but making sure the key reflects the row’s identity rather than its position.
This aligns with React’s own guidance:
Pitfall You might be tempted to use an item’s index in the array as its key. In fact, that’s what React will use if you don’t specify a key at all. But the order in which you render items will change over time if an item is inserted, deleted, or if the array gets reordered. Index as a key often leads to subtle and confusing bugs. (https://react.dev/learn/rendering-lists#rules-of-keys)
I included a sandbox demo showing how the current implementation causes focus loss.