fix: use originalDataIndex for tooltip dispatch in Bar#7273
fix: use originalDataIndex for tooltip dispatch in Bar#7273PavelVanecek merged 2 commits intorecharts:mainfrom
Conversation
|
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 (2)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughBar event handlers and active-state checks now use each entry's stable Changes
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)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/cartesian/Bar.tsx (1)
518-521:⚠️ Potential issue | 🟡 MinorUser-supplied event handlers for onMouseMove, onMouseDown, onMouseUp, onMouseOver, and onMouseOut still receive the render-array index.
adaptEventsOfChild(restOfAllOtherProps, entry, i)on Line 730 (and Line 518 in the background layer) continues to passi— the post-filter render index — to user-provided handlers for these event types. In sparse/zero-dimension filtered scenarios, this index won't match the original data array (e.g., when zero-height bars are filtered out).Note:
onClick,onMouseEnter, andonMouseLeaveare already correctly wired to useentry.originalDataIndexvia their respective context dispatch functions, so they are unaffected.Since the
BarMouseEventsignature is part of the publicBarAPI, changing it is a semver concern. However, existing tests do not verify the event handler index behavior foronMouseMove,onMouseDown,onMouseUp,onMouseOver, andonMouseOutin sparse/filtered data scenarios, so the impact of aligning them tooriginalDataIndexis unclear.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/cartesian/Bar.tsx` around lines 518 - 521, adaptEventsOfChild is passing the post-filter render index (i) into user event handlers for onMouseMove, onMouseDown, onMouseUp, onMouseOver, and onMouseOut, which causes mismatches when bars are filtered; update adaptEventsOfChild (or its call sites in Bar.tsx where adaptEventsOfChild(restOfAllOtherProps, entry, i) is used) so that the event payload delivered to those five handlers uses entry.originalDataIndex instead of i (keep onClick, onMouseEnter, onMouseLeave as-is), ensuring the BarMouseEvent index matches the original data index without changing the public event signature.
🧹 Nitpick comments (2)
test/component/Tooltip/Tooltip.payload.spec.tsx (2)
1523-1525: Minor: index-based lookup of the second.recharts-bargroup is fragile.
container.querySelectorAll('.recharts-bar')[1]assumes rendering order and class uniqueness that currently hold but aren't enforced. Consider targeting bydataKey(e.g., a class/selector derived frombar2) or by the<g>’sidset via theBaridprop to make the test resilient to internal layer reordering.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/component/Tooltip/Tooltip.payload.spec.tsx` around lines 1523 - 1525, The test currently uses index-based lookup (container.querySelectorAll('.recharts-bar')[1]) which is brittle; update the selection to target the second Bar more robustly by selecting the group by a stable identifier tied to the Bar (e.g., use the Bar's id or a dataKey-derived selector) instead of relying on order — replace the index lookup that produces bar2Group with a querySelector that matches the Bar id or data-key for "bar2" and then query that group for barMouseHoverTooltipSelector to get bar2Rect.
1505-1533: Consider also asserting the bar1 (row A) payload to guard against symmetric regressions.The test exercises only the second bar group where the original bug manifested. A companion assertion that hovers
bar1(row A) and verifies its payload is['bar1 : 0 ~ 10']would pin down both ends of the index mapping and catch a future regression where, for example, indices end up swapped or clamped. Cheap to add given the setup is already in place.🧪 Proposed additional assertion
const barGroups = container.querySelectorAll('.recharts-bar'); - const bar2Group = barGroups[1]; // second Bar component = bar2 + const bar1Group = barGroups[0]; + const bar1Rect = bar1Group.querySelector(barMouseHoverTooltipSelector); + assertNotNull(bar1Rect); + fireEvent.mouseOver(bar1Rect, { clientX: 100, clientY: 100 }); + act(() => { + vi.runOnlyPendingTimers(); + }); + expectTooltipPayload(container, '', ['bar1 : 0 ~ 10']); + + const bar2Group = barGroups[1]; // second Bar component = bar2 const bar2Rect = bar2Group.querySelector(barMouseHoverTooltipSelector); assertNotNull(bar2Rect); fireEvent.mouseOver(bar2Rect, { clientX: 200, clientY: 200 }); act(() => { vi.runOnlyPendingTimers(); }); expectTooltipPayload(container, '', ['bar2 : 5 ~ 20']);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/component/Tooltip/Tooltip.payload.spec.tsx` around lines 1505 - 1533, Add a companion assertion that also hovers the bar1 rect and verifies its tooltip payload to guard against symmetric index-mapping regressions: locate the first Bar group from container.querySelectorAll('.recharts-bar') (barGroups[0]), query its rect using the same barMouseHoverTooltipSelector, fire a mouseOver on that rect (with appropriate clientX/clientY), run pending timers like the existing act/vi.runOnlyPendingTimers call, and call expectTooltipPayload(container, '', ['bar1 : 0 ~ 10']) to validate the bar1 payload; reuse the existing barGroups, bar2Rect logic and expectTooltipPayload helper to keep the change minimal.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@src/cartesian/Bar.tsx`:
- Around line 518-521: adaptEventsOfChild is passing the post-filter render
index (i) into user event handlers for onMouseMove, onMouseDown, onMouseUp,
onMouseOver, and onMouseOut, which causes mismatches when bars are filtered;
update adaptEventsOfChild (or its call sites in Bar.tsx where
adaptEventsOfChild(restOfAllOtherProps, entry, i) is used) so that the event
payload delivered to those five handlers uses entry.originalDataIndex instead of
i (keep onClick, onMouseEnter, onMouseLeave as-is), ensuring the BarMouseEvent
index matches the original data index without changing the public event
signature.
---
Nitpick comments:
In `@test/component/Tooltip/Tooltip.payload.spec.tsx`:
- Around line 1523-1525: The test currently uses index-based lookup
(container.querySelectorAll('.recharts-bar')[1]) which is brittle; update the
selection to target the second Bar more robustly by selecting the group by a
stable identifier tied to the Bar (e.g., use the Bar's id or a dataKey-derived
selector) instead of relying on order — replace the index lookup that produces
bar2Group with a querySelector that matches the Bar id or data-key for "bar2"
and then query that group for barMouseHoverTooltipSelector to get bar2Rect.
- Around line 1505-1533: Add a companion assertion that also hovers the bar1
rect and verifies its tooltip payload to guard against symmetric index-mapping
regressions: locate the first Bar group from
container.querySelectorAll('.recharts-bar') (barGroups[0]), query its rect using
the same barMouseHoverTooltipSelector, fire a mouseOver on that rect (with
appropriate clientX/clientY), run pending timers like the existing
act/vi.runOnlyPendingTimers call, and call expectTooltipPayload(container, '',
['bar1 : 0 ~ 10']) to validate the bar1 payload; reuse the existing barGroups,
bar2Rect logic and expectTooltipPayload helper to keep the change minimal.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1fc966cd-6866-402c-a480-3618aa643ce9
📒 Files selected for processing (2)
src/cartesian/Bar.tsxtest/component/Tooltip/Tooltip.payload.spec.tsx
|
Re: Re: index-based selector — I kept it consistent with the existing tests in this file. Happy to change if preferred. Re: bar1 assertion — Added in the latest push. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7273 +/- ##
=======================================
Coverage 89.07% 89.07%
=======================================
Files 538 538
Lines 41020 41020
Branches 5563 5564 +1
=======================================
+ Hits 36538 36540 +2
+ Misses 4474 4472 -2
Partials 8 8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
9aa16de to
567237b
Compare
Bundle ReportChanges will increase total bundle size by 588 bytes (0.01%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: recharts/bundle-umdAssets Changed:
view changes for bundle: recharts/bundle-cjsAssets Changed:
view changes for bundle: recharts/bundle-treeshaking-cartesianAssets Changed:
view changes for bundle: recharts/bundle-es6Assets Changed:
|
Fixes #7261
Description
When
Barrenders with sparse data (some entries filtered out as zero-dimension), the tooltip event handlers (onMouseEnter,onMouseLeave,onClick) dispatch the render-array indexias the active tooltip index. After.filter(Boolean)removes null entries, this index no longer matches the original data array, so the tooltip resolves the wrong data entry.For example, with this data:
<Bar dataKey="bar2" />only renders one rectangle (for row B). That rectangle gets render indexi=0, but its actual position in the data array is1. Hovering it dispatchesactiveIndex: "0", which resolves to row A instead of row B.The
isActivecheck on line 598-600 already handles this correctly by usingentry.originalDataIndexinstead of the render index. This PR applies the same fix to the event handlers.Also fixed the same issue in
BarBackgroundwhereisActiveand event handlers had the same render-index problem.Test Plan
Added a regression test for vertical
BarChartwithshared={false}and sparse data — verifies that hovering bar2 (row B) shows bar2's payload, not bar1's.Summary by CodeRabbit
Bug Fixes
Tests