refactor: improve tbody key computation in DataTable#1380
Open
vinitkhandal717 wants to merge 2 commits intodevfrom
Open
refactor: improve tbody key computation in DataTable#1380vinitkhandal717 wants to merge 2 commits intodevfrom
vinitkhandal717 wants to merge 2 commits intodevfrom
Conversation
commit: |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the DataTable body remount key to better reflect changes in the displayed rows, addressing the reported issue where search/filter updates could render stale/irrelevant rows unless the component was force-remounted (Closes #1375).
Changes:
- Replaced the previous
tbodykey (based on length + first/last row IDs) with a computed hash derived from all row IDs. - Memoized the computed
tbodykey to avoid recomputation on unrelated renders.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+667
to
+669
| const tbodyKey = useMemo(() => { | ||
| return `tbody-${computeDataHash()}` | ||
| }, [currentData, idField]) |
| const id = String(currentData[i][idField]) | ||
| for (let j = 0; j < id.length; j++) { | ||
| hash = (hash << 5) - hash + id.charCodeAt(j) | ||
| hash = hash & hash // Convert to 32-bit integer |
Comment on lines
+640
to
+668
| // Compute a stable hash of the current data for React key | ||
| // This ensures proper remounting when data changes (search, filter, sort, pagination) | ||
| // Hash includes: data length + first ID + last ID + combined hash of all IDs | ||
| const computeDataHash = (): string => { | ||
| const len = currentData.length | ||
| if (len === 0) return 'empty' | ||
|
|
||
| // Get first and last IDs for quick comparison | ||
| const firstId = String(currentData[0][idField]) | ||
| const lastId = String(currentData[len - 1][idField]) | ||
|
|
||
| // Create a simple hash of all IDs for uniqueness | ||
| let hash = 0 | ||
| for (let i = 0; i < len; i++) { | ||
| const id = String(currentData[i][idField]) | ||
| for (let j = 0; j < id.length; j++) { | ||
| hash = (hash << 5) - hash + id.charCodeAt(j) | ||
| hash = hash & hash // Convert to 32-bit integer | ||
| } | ||
| } | ||
|
|
||
| // Convert negative hash to positive hex string | ||
| const hashHex = (hash >>> 0).toString(16) | ||
|
|
||
| return `${len}-${firstId}-${lastId}-${hashHex}` | ||
| } | ||
|
|
||
| const tbodyKey = useMemo(() => { | ||
| return `tbody-${computeDataHash()}` |
Comment on lines
+640
to
+665
| // Compute a stable hash of the current data for React key | ||
| // This ensures proper remounting when data changes (search, filter, sort, pagination) | ||
| // Hash includes: data length + first ID + last ID + combined hash of all IDs | ||
| const computeDataHash = (): string => { | ||
| const len = currentData.length | ||
| if (len === 0) return 'empty' | ||
|
|
||
| // Get first and last IDs for quick comparison | ||
| const firstId = String(currentData[0][idField]) | ||
| const lastId = String(currentData[len - 1][idField]) | ||
|
|
||
| // Create a simple hash of all IDs for uniqueness | ||
| let hash = 0 | ||
| for (let i = 0; i < len; i++) { | ||
| const id = String(currentData[i][idField]) | ||
| for (let j = 0; j < id.length; j++) { | ||
| hash = (hash << 5) - hash + id.charCodeAt(j) | ||
| hash = hash & hash // Convert to 32-bit integer | ||
| } | ||
| } | ||
|
|
||
| // Convert negative hash to positive hex string | ||
| const hashHex = (hash >>> 0).toString(16) | ||
|
|
||
| return `${len}-${firstId}-${lastId}-${hashHex}` | ||
| } |
Comment on lines
+667
to
+669
| const tbodyKey = useMemo(() => { | ||
| return `tbody-${computeDataHash()}` | ||
| }, [currentData, idField]) |
Comment on lines
+640
to
+642
| // Compute a stable hash of the current data for React key | ||
| // This ensures proper remounting when data changes (search, filter, sort, pagination) | ||
| // Hash includes: data length + first ID + last ID + combined hash of all IDs |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Refactor key/remount logic in TableBody
Issue Ticket
Closes #1375
Screen.Recording.2026-05-01.at.2.00.17.PM.mov
Uploading Screen Recording 2026-05-01 at 2.01.09 PM.mov…