fix(Brush): keep controlled startIndex/endIndex on data updates#7530
Conversation
When startIndex/endIndex are passed as props, a subsequent data update could still reset the Brush selection to the full range. chartDataSlice resets dataStartIndex/dataEndIndex whenever the new data does not match the previous end index, and nothing re-applied the controlled values afterwards since the syncing effect only depended on the index props. Add chartData as a dependency of that effect so a controlled selection is re-applied any time the data changes, not just when the index props themselves change. Fixes recharts#7462
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Walkthrough
ChangesBrush Controlled Indices Fix
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
test/cartesian/Brush.spec.tsx (1)
696-716: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider asserting selector call count to catch redundant dispatches.
Since this fix makes the effect re-fire on every
chartDatachange, this is a good spot to also assertspycall counts, per the coding guideline: "Verify the number of selector calls using the spy object fromcreateSelectorTestCaseto spot unnecessary re-renders and improve performance." This would catch any regression where the added dependency causes extra redundant dispatches/re-renders.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/cartesian/Brush.spec.tsx` around lines 696 - 716, Add an assertion on the selector invocation count in this Brush.spec.tsx test to guard against redundant re-renders caused by the ControlledBrushWithChangingData update. Use the existing spy from createSelectorTestCase around selectChartDataWithIndexes and verify the expected number of calls before and after the button-triggered data identity change, alongside the current dataStartIndex/dataEndIndex assertions, so regressions from the new chartData dependency are caught.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/cartesian/Brush.spec.tsx`:
- Around line 707-716: The Brush test is reading `spy.mock.calls` before the
Redux update queued by `BrushInternal` has been flushed. After
`fireEvent.click(button)`, advance fake timers with `vi.runOnlyPendingTimers()`
before asserting, since this test bypasses `createSelectorTestCase`’s render
helpers and the `autoBatchEnhancer` dispatch may still be pending. Keep the
existing assertions on `chartData`, `dataStartIndex`, and `dataEndIndex` in
`Brush.spec.tsx` after the timer flush.
---
Nitpick comments:
In `@test/cartesian/Brush.spec.tsx`:
- Around line 696-716: Add an assertion on the selector invocation count in this
Brush.spec.tsx test to guard against redundant re-renders caused by the
ControlledBrushWithChangingData update. Use the existing spy from
createSelectorTestCase around selectChartDataWithIndexes and verify the expected
number of calls before and after the button-triggered data identity change,
alongside the current dataStartIndex/dataEndIndex assertions, so regressions
from the new chartData dependency are caught.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2a9758fc-3371-438a-8624-eb175ebacb17
📒 Files selected for processing (2)
src/cartesian/Brush.tsxtest/cartesian/Brush.spec.tsx
Bundle ReportChanges will increase total bundle size by 1.06kB (0.02%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: recharts/bundle-cjsAssets Changed:
view changes for bundle: recharts/bundle-treeshaking-cartesianAssets Changed:
view changes for bundle: recharts/bundle-umdAssets Changed:
view changes for bundle: recharts/bundle-es6Assets Changed:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7530 +/- ##
=======================================
Coverage 88.17% 88.17%
=======================================
Files 613 613
Lines 14246 14246
Branches 3580 3580
=======================================
Hits 12562 12562
Misses 1494 1494
Partials 190 190 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Redux's autoBatchEnhancer queues dispatches behind requestAnimationFrame, and this suite runs with fake timers globally. The controlled-index test read spy.mock.calls right after fireEvent.click without flushing that queue, so the assertion could observe a stale value depending on action ordering.
|
Sorry @momomuchu I merged #7542 and it appears that caused conflicts or your PR. May I please ask you to resolve Edit: nevermind sorry it all looks good now |
Description
Controlled
startIndex/endIndexon<Brush>get silently overwritten when the chartdataarray changes. The sync effect that copies the props into Redux only depended on the index props themselves, so oncechartDataSliceresetdataStartIndex/dataEndIndexon a data update, nothing re-applied the controlled values. AddingchartDatato that effect's dependency array makes it re-assert the controlled indices any time the data changes, not just when the index props change.This does not touch
chartDataSlice.tsor the reducer's reset behavior at all, and does not affect uncontrolled Brush usage in any way (setDataStartEndIndexesis a no-op when both indices are undefined). It's unrelated to the referential-equality discussion in #7021 - that was about whether Brush should treat a same-length new array reference as "unchanged" for internally-managed selection state, which is a separate question from what a controlled component does with props it was explicitly given. This PR doesn't reopen that; it just makes controlled props actually win, the same way a controlled<input value>would.Related Issue
Fixes #7462
Motivation and Context
Bug fix. Controlled Brush is a documented pattern and currently doesn't work reliably across data updates.
How Has This Been Tested?
Added a unit test in test/cartesian/Brush.spec.tsx that renders a controlled Brush, changes the data array to a new reference of the same length, and asserts the controlled indices are preserved. Ran the full unit suite locally, all green.
Types of changes
Checklist:
Summary by CodeRabbit