fix(table-core): don't fire onExpandedChange when resetExpanded is a no-op - #6519
Open
Faithfinder wants to merge 1 commit into
Open
fix(table-core): don't fire onExpandedChange when resetExpanded is a no-op#6519Faithfinder wants to merge 1 commit into
Faithfinder wants to merge 1 commit into
Conversation
…no-op table_resetExpanded built a fresh state object and always routed it through onExpandedChange, without comparing against the current expanded state. Its siblings all compare first: table_resetPageIndex and table_resetPageSize early-return when the value already matches, and row_toggleExpanded and table_toggleAllRowsExpanded gained the same guard in TanStack#6501. Since TanStack#6499 wired the expansion auto-reset into createCoreRowModel, that unguarded write fires on every data reference change. For a controlled table whose data is not referentially stable, the new-but-equal map re-renders the consumer, which produces another new data reference, and the cycle repeats without bound. Compare the target state against table.atoms.expanded?.get() and return early when they match, for both defaultState branches. Expanded-all compares by identity, maps key-by-key.
Contributor
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (14)
📝 WalkthroughWalkthrough
ChangesExpanded reset behavior
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
table_resetExpandedbuilds a fresh state object and always callsonExpandedChange, without comparing against the current state. Every sibling compares first:table_resetPageIndex/table_resetPageSize— early-return when the value already matchesrow_toggleExpanded/table_toggleAllRowsExpanded— early-return, added in fix(table-core): correct expanded/paginated state contents and sorting toggle defaults #6501table_resetExpanded— no guardSince #6499 wired the expansion auto-reset into
createCoreRowModel, that unguarded write fires on everydatareference change:dataidentity changes → core row model recomputes →table_autoResetExpanded→table_resetExpanded→onExpandedChange(newEmptyMap)→ consumer re-renders → newdatareference → repeat.Measured with this repo's
react-tableon React 19.2, controlledexpandedviauseState,getRowCanExpand: () => true, and one row-model read during render, capped at 50 renders:dataonExpandedChangecallsitems ?? []items ?? []+ this fixitems ?? STABLE_EMPTY_ARRAYitems ?? []+autoResetExpanded: falseStable
datais documented, and the loop needs an unstable reference — this is a user mistake in the first instance. The case for guarding anyway is that the punishment is disproportionate and near-undiagnosable: nothing in the stack points at expansion, and the tab is too unresponsive to profile. The pagination resets already absorb exactly this mistake, and v8 absorbed it too — it passedtable.initialState?.expandedthrough by reference, sosetExpanded(sameRef)hit the identity check inuseState. v9 clones it, so the reference is always new.Change
table_resetExpandedcompares its target againsttable.atoms.expanded?.get()(asrow_toggleExpandedalready does) and returns early when they match —trueby identity, maps key-by-key, bothdefaultStatebranches.Two existing tests asserted that the reset fires when the current state already equals the target. They now diverge the state first, so they still cover the reset value.
Summary by CodeRabbit
Bug Fixes
Documentation