Skip to content

Refactor barSelectors so that they read axis IDs from state instead of props#6723

Merged
ckifer merged 1 commit intomainfrom
barselector-refactor
Dec 3, 2025
Merged

Refactor barSelectors so that they read axis IDs from state instead of props#6723
ckifer merged 1 commit intomainfrom
barselector-refactor

Conversation

@PavelVanecek
Copy link
Collaborator

@PavelVanecek PavelVanecek commented Dec 3, 2025

Description

Select data from state instead of props to keep the API simpler.

Summary by CodeRabbit

  • Refactor

    • Simplified internal data retrieval architecture for bar chart components by consolidating identifier resolution pathways.
  • Tests

    • Updated test cases to align with refactored data retrieval mechanisms, including explicit identifier assignments and corresponding selector invocations.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

Walkthrough

This pull request refactors bar selector signatures to accept a single GraphicalItemId (bar identifier) instead of separate xAxisId and yAxisId parameters. Selectors now derive axis associations internally from per-bar state settings, reducing argument count and centralizing bar-to-axis mapping logic.

Changes

Cohort / File(s) Summary
Selector refactoring
src/state/selectors/barSelectors.ts
Refactors 13+ selector signatures to accept GraphicalItemId instead of separate axis ids. Introduces selectSynchronisedBarSettings, selectXAxisIdFromBar, selectYAxisIdFromBar helpers to derive axis associations from bar state. Updates computation pipelines (sizing, stacking, rectangles) to route through per-bar state resolution with null/undefined guards.
Consumer update
src/cartesian/Bar.tsx
Updates selectBarRectangles invocation from (state, xAxisId, yAxisId, isPanorama, id, cells) to (state, id, isPanorama, cells) to match new selector signature.
Test updates
test/cartesian/Bar.truncateByDomain.spec.tsx, test/cartesian/XAxis/XAxis.barSize.spec.tsx, test/cartesian/XAxis/XAxis.padding.spec.tsx, test/chart/BarChart.spec.tsx
Update selector calls across multiple test files to use new bar-id-first signatures. Replace numeric axis indices with explicit bar/test identifiers. Add explicit id attributes to Bar components and update expectations to match new identifier scheme.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Primary concerns:
    • Verify axis derivation logic in new helpers (selectXAxisIdFromBar, selectYAxisIdFromBar) correctly maps bar ids to their corresponding axes
    • Check null/undefined guards throughout the selector refactor to ensure no unhandled edge cases when bar-to-axis mapping is missing
    • Confirm all 13+ public selector signature changes are coordinated across call sites
    • Validate that test identifier changes (explicit ids vs. regex patterns) reflect real component behavior and don't mask issues

Suggested reviewers

  • ckifer

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimal but related to the changes. However, it lacks required template sections like Related Issue, Motivation and Context, How Has This Been Tested, and Types of changes. Add missing template sections including Related Issue (link to #6723 or associated issue), detailed Motivation and Context explaining why this simplifies the API, and descriptions of testing performed and the type of change (breaking change, feature, etc.).
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main refactoring: bar selectors now derive axis IDs from state instead of accepting them as parameters.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch barselector-refactor

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 492be75 and ed57c1e.

📒 Files selected for processing (6)
  • src/cartesian/Bar.tsx (1 hunks)
  • src/state/selectors/barSelectors.ts (8 hunks)
  • test/cartesian/Bar.truncateByDomain.spec.tsx (1 hunks)
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx (1 hunks)
  • test/cartesian/XAxis/XAxis.padding.spec.tsx (1 hunks)
  • test/chart/BarChart.spec.tsx (33 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Run type checking on the codebase using npm run check-types

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

Files:

  • test/cartesian/XAxis/XAxis.padding.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
  • src/cartesian/Bar.tsx
  • src/state/selectors/barSelectors.ts
{test,www/test}/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Write unit tests in the test or www/test directories with .spec.tsx file extension

Files:

  • test/cartesian/XAxis/XAxis.padding.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
test/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Aim for 100% unit test code coverage when writing new code

Files:

  • test/cartesian/XAxis/XAxis.padding.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • test/cartesian/XAxis/XAxis.padding.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
  • src/cartesian/Bar.tsx
  • src/state/selectors/barSelectors.ts
test/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (test/README.md)

test/**/*.{test,spec}.{ts,tsx}: Aim for 100% unit test code coverage when writing new code
Prefer to use the createSelectorTestCase helper function when writing or modifying tests
Use the expectLastCalledWith helper function instead of expect(spy).toHaveBeenLastCalledWith(...) for better typing and autocompletion
Verify the number of selector calls using the spy object from createSelectorTestCase to spot unnecessary re-renders and improve performance
Mock getBoundingClientRect in tests using the helper function provided in test/helper/MockGetBoundingClientRect.ts
Use vi.useFakeTimers() in all tests due to Redux autoBatchEnhancer dependency on timers and requestAnimationFrame
Call vi.runOnlyPendingTimers() to advance timers after renders when not using createSelectorTestCase helper, and avoid vi.runAllTimers() to prevent infinite loops
Use userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers }) or the userEventSetup helper function from test/helper/userEventSetup.ts when creating userEvent instances
When testing tooltips on hover, use vi.runOnlyPendingTimers() after each userEvent.hover() call or use the showTooltip helper function from tooltipTestHelpers.ts to account for requestAnimationFrame delays

Files:

  • test/cartesian/XAxis/XAxis.padding.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

When running unit tests, prefer to run a single test file using npm run test -- path/to/TestFile.spec.tsx rather than running all tests with npm test

Files:

  • test/cartesian/XAxis/XAxis.padding.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
src/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

Run ESLint and Prettier on the codebase using npm run lint

Files:

  • src/cartesian/Bar.tsx
  • src/state/selectors/barSelectors.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Files:

  • src/cartesian/Bar.tsx
  • src/state/selectors/barSelectors.ts
🧠 Learnings (9)
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Verify the number of selector calls using the spy object from `createSelectorTestCase` to spot unnecessary re-renders and improve performance

Applied to files:

  • test/cartesian/XAxis/XAxis.padding.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Prefer to use the `createSelectorTestCase` helper function when writing or modifying tests

Applied to files:

  • test/cartesian/XAxis/XAxis.padding.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Mock `getBoundingClientRect` in tests using the helper function provided in `test/helper/MockGetBoundingClientRect.ts`

Applied to files:

  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Call `vi.runOnlyPendingTimers()` to advance timers after renders when not using `createSelectorTestCase` helper, and avoid `vi.runAllTimers()` to prevent infinite loops

Applied to files:

  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/chart/BarChart.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use the `expectLastCalledWith` helper function instead of `expect(spy).toHaveBeenLastCalledWith(...)` for better typing and autocompletion

Applied to files:

  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to test/component/**/*.spec.tsx : Use React Testing Library for testing component interactions and behavior upon rendering

Applied to files:

  • test/cartesian/XAxis/XAxis.barSize.spec.tsx
  • test/chart/BarChart.spec.tsx
📚 Learning: 2025-11-23T13:30:10.395Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.395Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • test/chart/BarChart.spec.tsx
📚 Learning: 2025-11-19T14:08:01.728Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6659
File: www/src/components/GuideView/Performance/index.tsx:232-250
Timestamp: 2025-11-19T14:08:01.728Z
Learning: In Recharts version 3.4.2, object-as-prop optimizations were introduced to reduce unnecessary re-renders when new object references are passed as props. This affects the recommendation for the `react-perf/jsx-no-new-object-as-prop` ESLint rule.

Applied to files:

  • test/chart/BarChart.spec.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to storybook/stories/**/*.stories.tsx : Update Storybook stories when APIs have been changed to ensure they work as expected

Applied to files:

  • test/chart/BarChart.spec.tsx
🧬 Code graph analysis (3)
test/cartesian/XAxis/XAxis.padding.spec.tsx (1)
src/state/selectors/barSelectors.ts (1)
  • selectBarBandSize (189-216)
test/cartesian/Bar.truncateByDomain.spec.tsx (1)
src/state/selectors/barSelectors.ts (1)
  • selectBarRectangles (475-554)
test/cartesian/XAxis/XAxis.barSize.spec.tsx (1)
src/state/selectors/barSelectors.ts (4)
  • selectBarBandSize (189-216)
  • selectAllBarPositions (373-388)
  • selectBarSizeList (180-187)
  • selectBarCartesianAxisSize (135-146)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build, Test, Pack
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (23)
src/state/selectors/barSelectors.ts (12)

36-53: LGTM - New per-bar helper selectors are well-structured.

The new pickIsPanorama, pickBarId, selectSynchronisedBarSettings, selectXAxisIdFromBar, and selectYAxisIdFromBar helpers cleanly centralize axis ID resolution. Using createSelector for memoization is appropriate here.


55-58: Simplified signature for selectMaxBarSize.

The selector now only requires id: GraphicalItemId instead of axis IDs + id. This aligns with the PR objective of deriving axis info internally.


80-97: selectAllVisibleBars now derives axis IDs internally.

The selector filters bars based on axis IDs resolved from the provided bar id. The logic correctly uses layout to determine whether to filter by xAxisId or yAxisId.


118-133: Good defensive null checks in selectBarStackGroups.

The function properly guards against undefined axis IDs before proceeding with stack group selection. Returning undefined early prevents downstream errors.


135-146: selectBarCartesianAxisSize properly handles missing axis IDs.

The function is not memoized with createSelector, which is acceptable for a simple selector that primarily delegates to other selectors.


189-216: selectBarBandSize correctly handles edge cases.

The function properly returns undefined when bar settings or axis IDs are unavailable, preventing downstream computation errors.


218-238: selectAxisBandSize follows the same defensive pattern.

Consistent null guards for axis IDs before proceeding with band size calculation.


373-388: selectAllBarPositions input selectors updated correctly.

The selector composition now uses the refactored selectors that derive axis IDs internally. The selectMaxBarSize dependency correctly receives only the bar id (no axis IDs).


390-420: New axis/tick selectors with null guards.

selectXAxisWithScale, selectYAxisWithScale, selectXAxisTicks, and selectYAxisTicks all properly check for undefined axis IDs before delegating. This is a clean abstraction layer.


422-441: selectBarPosition properly handles null cases.

The selector checks both allBarPositions and barSettings for null before attempting to find the position, preventing runtime errors.


466-473: selectStackedDataOfItem correctly uses refactored dependencies.

The selector now uses selectBarStackGroups and selectSynchronisedBarSettings which derive axis info from the bar id.


475-554: selectBarRectangles refactored to use id-based selectors.

The main selector now uses the new per-bar helpers for axis and tick resolution. The comprehensive null checks in the result function (lines 511-522) properly guard against missing dependencies.

src/cartesian/Bar.tsx (1)

742-742: Selector invocation updated to new API.

The call to selectBarRectangles now correctly uses the simplified signature with props.id as the bar identifier instead of separate axis IDs. The axis resolution is now handled internally by the selector.

test/cartesian/XAxis/XAxis.padding.spec.tsx (1)

34-34: Test updated to use new selector signature.

The selectBarBandSize call now uses the bar id directly instead of axis indices. The Bar component at line 41 correctly provides the matching id="my-bar-id" prop.

test/cartesian/Bar.truncateByDomain.spec.tsx (1)

89-89: Test updated for new selectBarRectangles signature.

The selector call now correctly uses the bar id 'bar-wins' directly. The test properly uses createSelectorTestCase helper as per coding guidelines.

test/chart/BarChart.spec.tsx (7)

299-306: Test setup correctly uses bar id for selector calls.

The selectAllVisibleBars and selectBarSizeList calls now use 'my-bar-id' instead of axis indices. The Bar component at line 305 correctly provides the matching id="my-bar-id" prop.


1076-1077: Stacked bars test correctly uses distinct bar ids.

Both selectBarRectangles calls now reference the specific bar ids ('bar-uv' and 'bar-pv') that match the Bar component declarations at lines 1090-1093.


1397-1401: Bar components given explicit ids for multi-axis test.

The Bar components now have explicit id props ('bar-axis-one', 'bar-axis-two') that align with the selector calls in the tests. This makes the test more explicit and maintainable.


1446-1471: Multi-axis selector tests updated consistently.

Both selectAllVisibleBars calls at lines 1446 and 1468 now use the bar ids to derive which bars are visible. The expected results correctly reflect the new id-based filtering.


1846-1847: Vertical chart test Bar components have explicit ids.

The Bar components now have explicit ids ('bar-xaxis-2', 'bar-xaxis-1') that match the selector calls in subsequent tests.


2266-2266: Brush panorama test updated for new API.

The selectAllBarPositions call correctly uses 'my-bar-id' to match the Bar component at line 2272.


2417-2418: Boxplot simulation test uses explicit bar id.

Both selectAllBarPositions and selectBarRectangles calls now use 'my-bar-id' consistently with the Bar component at line 2430.

test/cartesian/XAxis/XAxis.barSize.spec.tsx (1)

117-124: Updated bar selector calls correctly use bar id

Switching selectBarBandSize, selectAllBarPositions, selectBarSizeList, and selectBarCartesianAxisSize to be invoked with 'my-bar-id' (matching the <Bar id="my-bar-id" />) and the existing isPanorama = false flag aligns with the new selector signatures and keeps the test semantics intact. No issues spotted here.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@PavelVanecek PavelVanecek added the refactor PRs that refactor existing code label Dec 3, 2025
@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

❌ Patch coverage is 98.57143% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 94.02%. Comparing base (3599a10) to head (ed57c1e).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
src/state/selectors/barSelectors.ts 98.55% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6723      +/-   ##
==========================================
- Coverage   94.03%   94.02%   -0.01%     
==========================================
  Files         500      500              
  Lines       42662    42688      +26     
  Branches     4901     4917      +16     
==========================================
+ Hits        40116    40139      +23     
- Misses       2541     2544       +3     
  Partials        5        5              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codecov
Copy link

codecov bot commented Dec 3, 2025

Bundle Report

Changes will increase total bundle size by 2.69kB (0.1%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
recharts/bundle-cjs 1.15MB 1.17kB (0.1%) ⬆️
recharts/bundle-es6 996.88kB 1.14kB (0.11%) ⬆️
recharts/bundle-umd 520.09kB 368 bytes (0.07%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: recharts/bundle-umd

Assets Changed:

Asset Name Size Change Total Size Change (%)
Recharts.js 368 bytes 520.09kB 0.07%
view changes for bundle: recharts/bundle-es6

Assets Changed:

Asset Name Size Change Total Size Change (%)
cartesian/Bar.js -18 bytes 25.36kB -0.07%
state/selectors/barSelectors.js 1.16kB 14.19kB 8.92% ⚠️
view changes for bundle: recharts/bundle-cjs

Assets Changed:

Asset Name Size Change Total Size Change (%)
cartesian/Bar.js -18 bytes 27.07kB -0.07%
state/selectors/barSelectors.js 1.19kB 15.86kB 8.13% ⚠️

@ckifer ckifer merged commit 4499a65 into main Dec 3, 2025
40 of 43 checks passed
@PavelVanecek PavelVanecek deleted the barselector-refactor branch December 3, 2025 01:55
@PavelVanecek PavelVanecek mentioned this pull request Mar 7, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor PRs that refactor existing code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants