Skip to content

fix: DataTable sorting, filtering, resizing broken with React Compiler#29

Merged
joshuapare merged 2 commits into
mainfrom
feat/table-fixes
Mar 12, 2026
Merged

fix: DataTable sorting, filtering, resizing broken with React Compiler#29
joshuapare merged 2 commits into
mainfrom
feat/table-fixes

Conversation

@joshuapare
Copy link
Copy Markdown
Contributor

@joshuapare joshuapare commented Mar 12, 2026

Summary

  • Missing .SortButton CSS class caused header buttons to render as unstyled HTML, producing the ugly generic button appearance
  • React Compiler memoization break: useReactTable() returns a stable reference that mutates internally — Compiler memoized consumer JSX based on this identity, preventing child re-renders on state changes. Fixed by returning a new-identity spread object from useDataTable via useMemo with all managed state as dependencies
  • Global filter silently disabled: enableFilters was set to false when only globalFilter was enabled (not filtering), causing TanStack Table's column.getCanGlobalFilter() to return false for all columns

Test plan

  • 18 DataTable tests pass (including 10 new bug regression tests)
  • Full suite: 856 tests pass, zero regressions
  • Browser-verified: sorting reorders data with indicators, search filters rows, column resizing updates CSS vars, headers properly styled

Summary by CodeRabbit

  • New Features

    • Global filtering enabled for DataTable to improve data discovery.
  • Style

    • Refined sort-button styling for more consistent header appearance.
  • Bug Fixes

    • Improved filtering and sorting behaviors to address edge cases users encountered.
  • Tests

    • Added comprehensive tests covering sorting, searching, column resizing, column ordering, and filtering to increase reliability.

- Add missing .SortButton CSS class that caused unstyled header buttons
- Return new-identity table object from useDataTable via useMemo spread,
  so React Compiler detects state changes in consumer components
- Fix enableFilters to include globalFilter, preventing columns from
  being unfilterable when only globalFilter feature is enabled
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

Adds a comprehensive bug-focused test file for DataTable, adds a SortButton CSS class, inserts a no-op marker in useColumnSizeVars, and changes useDataTable to return a new object identity and enable filters when features.globalFilter is set.

Changes

Cohort / File(s) Summary
DataTable Tests
packages/base-ui/src/components/data-table/DataTable.bugs.test.tsx
Adds a 362-line test file with multiple bug-focused suites covering sorting, sort button styling, search/global filtering, column resizing, column ordering, and column filtering using React Testing Library, vitest, and user-event.
DataTable Styling
packages/base-ui/src/components/data-table/DataTable.module.css
Adds a new .SortButton CSS class with all: unset, inline-flex layout, centered alignment, gap, inherited font/color, and cursor pointer for header sort buttons.
Hook tweaks
packages/base-ui/src/components/data-table/hooks/useColumnSizeVars.ts, packages/base-ui/src/components/data-table/hooks/useDataTable.ts
Adds a no-op string marker in useColumnSizeVars. Modifies useDataTable to return a newly spread object (changing reference identity) and expands enableFilters to be true when features.filtering or features.globalFilter is enabled.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I hopped through rows and gave a cheer,

Sorted, resized, and filtered here,
A tiny CSS button, neat and spry,
Hooks refreshed — a brand new try,
Bugs beware, the rabbit's nigh!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and accurately describes the main changes: fixing DataTable sorting, filtering, and resizing issues caused by React Compiler behavior. It matches the primary objectives and aligns with the substantial changes made to CSS, hooks, and tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/table-fixes

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/base-ui/src/components/data-table/DataTable.bugs.test.tsx`:
- Around line 319-329: The test currently enables both features.filtering and
features.globalFilter so it doesn't exercise the regression where global
filtering should work when filtering is disabled; update the test setup and
render to set features.filtering: false and features.globalFilter: true (adjust
the useDataTable call and the DataTable.Root props where features is passed) so
the hook paths in useDataTable (and any enableFilters logic) are exercised with
filtering disabled but globalFilter enabled; ensure any expectations/assertions
remain valid for this configuration.

In `@packages/base-ui/src/components/data-table/DataTable.module.css`:
- Around line 210-220: The .SortButton rule makes the header button a full-width
flex container which forces child alignment to flex-start and breaks
centered/right column alignment; update the .SortButton selector to use display:
inline-flex (not full-width flex), remove or stop forcing width: 100% and
height: 100%, and add justify-content: inherit so the button inherits the
header's alignment; this preserves numeric/center/right alignment while keeping
the button layout and gap styles.

In `@packages/base-ui/src/components/data-table/hooks/useColumnSizeVars.ts`:
- Line 1: Move the module-level directive "'use no memo';" into the start of the
useColumnSizeVars hook body so the compiler opt-out is scoped only to that
custom hook; locate the useColumnSizeVars function in this file and place the
directive as the first statement inside its function body (remove the
module-level occurrence) ensuring no other exports in the module are affected.

In `@packages/base-ui/src/components/data-table/hooks/useDataTable.ts`:
- Line 3: Remove the useMemo import/usages in useDataTable and always return a
fresh spread of the table object so consumers get a new identity each render:
stop memoizing the returned object (remove any useMemo wrapping around the
table), ensure the hook still calls useReactTable as before (look for the
`useDataTable` function and the `useReactTable` call) and return `{ ...table }`
directly; also remove `useMemo` from the import list to keep imports tidy.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 36850447-5479-4b5c-a65a-083b0d53d21c

📥 Commits

Reviewing files that changed from the base of the PR and between d0c6abe and 0921b31.

📒 Files selected for processing (4)
  • packages/base-ui/src/components/data-table/DataTable.bugs.test.tsx
  • packages/base-ui/src/components/data-table/DataTable.module.css
  • packages/base-ui/src/components/data-table/hooks/useColumnSizeVars.ts
  • packages/base-ui/src/components/data-table/hooks/useDataTable.ts

Comment thread packages/base-ui/src/components/data-table/DataTable.bugs.test.tsx Outdated
Comment thread packages/base-ui/src/components/data-table/DataTable.module.css
Comment thread packages/base-ui/src/components/data-table/hooks/useColumnSizeVars.ts Outdated
Comment thread packages/base-ui/src/components/data-table/hooks/useDataTable.ts Outdated
- Test globalFilter with filtering:false to exercise the actual regression
- SortButton: use inline-flex + justify-content:inherit for alignment
- Scope 'use no memo' to useColumnSizeVars function body
- Drop useMemo wrapper; return plain spread for simplicity
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/base-ui/src/components/data-table/DataTable.bugs.test.tsx`:
- Around line 222-235: The test "resize handle has mouseDown handler that starts
resizing" leaves a started resize active and may pollute other tests; after
firing fireEvent.mouseDown(firstHandle, { clientX: 100 }) add a matching
fireEvent.mouseUp(...) to end the resize (preferably on document or the same
element) so any global mouse listeners are removed; update the test around
ResizableTable / firstHandle to call mouseUp as cleanup to ensure
data-ov-resizing resets and no global listeners remain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c7317b33-6fe5-48ba-b90c-347a1bd2e68c

📥 Commits

Reviewing files that changed from the base of the PR and between 0921b31 and 4562b52.

📒 Files selected for processing (4)
  • packages/base-ui/src/components/data-table/DataTable.bugs.test.tsx
  • packages/base-ui/src/components/data-table/DataTable.module.css
  • packages/base-ui/src/components/data-table/hooks/useColumnSizeVars.ts
  • packages/base-ui/src/components/data-table/hooks/useDataTable.ts

Comment on lines +222 to +235
it('resize handle has mouseDown handler that starts resizing', () => {
renderWithTheme(<ResizableTable />);
const resizeHandles = screen.getAllByRole('separator');
const firstHandle = resizeHandles[0]!;

// Initially not resizing
expect(firstHandle).toHaveAttribute('data-ov-resizing', 'false');

// Fire mouseDown to start resizing
fireEvent.mouseDown(firstHandle, { clientX: 100 });

// After mouseDown, should be in resizing state
expect(firstHandle).toHaveAttribute('data-ov-resizing', 'true');
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding a mouseUp cleanup to avoid test pollution.

The test fires mouseDown to start resizing but doesn't fire mouseUp to end it. While this may not affect the current test in isolation, it could leave global event listeners attached if the component registers them on mouseDown.

🧪 Suggested improvement
     // Fire mouseDown to start resizing
     fireEvent.mouseDown(firstHandle, { clientX: 100 });

     // After mouseDown, should be in resizing state
     expect(firstHandle).toHaveAttribute('data-ov-resizing', 'true');
+
+    // Cleanup: end the resize operation
+    fireEvent.mouseUp(firstHandle);
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/base-ui/src/components/data-table/DataTable.bugs.test.tsx` around
lines 222 - 235, The test "resize handle has mouseDown handler that starts
resizing" leaves a started resize active and may pollute other tests; after
firing fireEvent.mouseDown(firstHandle, { clientX: 100 }) add a matching
fireEvent.mouseUp(...) to end the resize (preferably on document or the same
element) so any global mouse listeners are removed; update the test around
ResizableTable / firstHandle to call mouseUp as cleanup to ensure
data-ov-resizing resets and no global listeners remain.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 12, 2026

Merging this PR will degrade performance by 86.44%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 12 regressed benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime mount section 393.4 µs 1,897.3 µs -79.27%
WallTime mount 1000 98.1 ms 441.1 ms -77.76%
WallTime mount div 434.9 µs 2,008.2 µs -78.35%
WallTime mount 1000 35.3 ms 192.3 ms -81.63%
WallTime variant change 213.5 µs 1,574.7 µs -86.44%
WallTime mount 560.7 µs 2,665.6 µs -78.97%
WallTime mount 100 rows 41.7 ms 218.4 ms -80.92%
WallTime mount 1000 rows 436.4 ms 2,036.5 ms -78.57%
WallTime mount 1000 810.3 ms 1,953.9 ms -58.53%
WallTime checked toggle 1.2 ms 5 ms -75.27%
WallTime mount 1.8 ms 5.7 ms -68.13%
WallTime mount with decorators 614.5 µs 3,192.1 µs -80.75%

Comparing feat/table-fixes (4562b52) with main (ea3c565)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (d0c6abe) during the generation of this report, so ea3c565 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@joshuapare joshuapare merged commit e310435 into main Mar 12, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant