Skip to content

Multiple renames for clarity and consistency - #3967

Merged
nstepien merged 33 commits into
mainfrom
clarity
Oct 21, 2026
Merged

nstepien merged 33 commits into
mainfrom
clarity

Conversation

@nstepien

@nstepien nstepien commented Feb 21, 2026 •

Copy link
Copy Markdown
Collaborator

I've renamed a few components/types for clarity and consistency.

  • Removed "formatter" from names, it's legacy nomenclature
  • Removed "renderer" from some names, virtually all React components are "renderers" so it's redundant.
    It's like naming components *Component.
  • To help differentiate between the renderers.renderCell and column.renderCell,
    I've changed some names from *CellProps to *CellContentProps for example
  • Removed some default exports so we use the same named import everywhere

Breaking changes:

  • cell content:
    • RenderCellProps -> RenderCellContentProps
    • RenderHeaderCellProps -> RenderHeaderCellContentProps
    • RenderSummaryCellProps -> RenderSummaryCellContentProps
    • RenderGroupCellProps -> RenderGroupCellContentProps
    • RenderEditCellProps -> RenderEditCellContentProps
  • CellRendererProps -> RenderCellProps
    • while this is consistent with everything else now (Render*Props pattern), it'll conflict with the older RenderCellProps type name, need to be careful when updating RDG
    • the new RenderCellProps has a different shape and no default for TSummaryRow, so code still using the old RenderCellProps fails type checking instead of silently changing meaning
  • SelectCellFormatter -> SelectCheckbox
  • RenderRowProps['activeCellEditor'] is now typed with the props the editor cell actually receives, instead of RenderEditCellProps

Other changes:

  • Cell events (CellMouseEvent, CellKeyboardEvent) now inherit from the React event instead of copying its properties. As with React events, currentTarget is null after the handler returns.
  • useLatestFunc is typed without any or @ts-expect-error
  • TreeDataGrid groups rows without allocating temporary arrays
  • README: the *ContentProps types and the default content renderers are described as cell content renderers, and rowGrouper and groupIdGetter have performance notes
  • Website: renamed demo components (CellExpanderFormatter -> CellExpander, DraggableRowRenderer -> DraggableRow, FilterRenderer -> FilterCell), and the infinite scrolling demo uses useTransition

@codecov-commenter

codecov-commenter commented Feb 21, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.35%. Comparing base (6f1f5cf) to head (618d87b).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3967   +/-   ##
=======================================
  Coverage   98.35%   98.35%           
=======================================
  Files          45       45           
  Lines        1951     1951           
  Branches      727      727           
=======================================
  Hits         1919     1919           
  Misses         32       32           
Files with missing lines Coverage Δ
src/Cell.tsx 100.00% <100.00%> (ø)
src/Columns.tsx 100.00% <100.00%> (ø)
src/DataGrid.tsx 98.88% <100.00%> (+<0.01%) ⬆️
src/EditCell.tsx 97.14% <ø> (ø)
src/GroupedRow.tsx 100.00% <100.00%> (ø)
src/Row.tsx 100.00% <100.00%> (ø)
src/SummaryCell.tsx 100.00% <ø> (ø)
src/TreeDataGrid.tsx 94.44% <100.00%> (+0.03%) ⬆️
src/cellRenderers/SelectCheckbox.tsx 100.00% <100.00%> (ø)
src/cellRenderers/renderToggleGroup.tsx 100.00% <100.00%> (ø)
... and 6 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@nstepien nstepien self-assigned this Feb 23, 2026
Comment thread src/TreeDataGrid.tsx
function groupRows(
rows: readonly R[],
[groupByKey, ...remainingGroupByKeys]: readonly string[],
groupByIndex: number,

@nstepien nstepien Feb 23, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Refactored this so we don't allocate temp arrays

fn: Maybe<(...args: Args) => void>
): Maybe<(...args: Args) => void>;

export function useLatestFunc<Args extends unknown[]>(fn: Maybe<(...args: Args) => void>) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We can implement this without any/@ts-expect-error!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Don't think I fully understand this TS code :)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Me neither, it's some technical limitation of using unknown vs any I guess 🤷‍♂️

Comment thread src/utils/eventUtils.ts
Object.setPrototypeOf(cellEvent, Object.getPrototypeOf(event));

return cellEvent;
});

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This creates a new object that inherits from the event object, and adds preventGridDefault/isGridDefaultPrevented property descriptors

WDYT?

Comment thread src/DataGrid.tsx Outdated
Comment thread src/DataGrid.tsx
const columnWidth = getColumnWidth(column);
const colSpan = column.colSpan?.({ type: 'ROW', row: rows[rowIdx] }) ?? 1;
const { insetInlineStart, ...style } = getCellStyle(column, colSpan);
const style = getCellStyle(column, colSpan);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

-1 object

@nstepien
nstepien marked this pull request as ready for review February 23, 2026 23:26
nstepien and others added 9 commits July 26, 2026 22:42
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
React does not mark state updates after an `await` as part of the
transition, so `setRows` committed in a separate render from `isPending`
turning false, briefly showing the loading message over the new rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The descriptions of the `*ContentProps` types and of the default content
renderers still called them cell renderers, the term `RenderCellProps`
now uses for `renderers.renderCell`. Call them cell content renderers,
and name the column property each type is for.

Also restore the sorted order of two type import lists that the
`CellRendererProps` -> `RenderCellProps` rename had broken.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
They hold `format` functions now, not `Intl` formatter objects, so call
them `formatDate` and `formatCurrency`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nstepien
nstepien added this pull request to stack #4218 October 21, 2026 22:07
@nstepien
nstepien merged commit e5742ee into main Oct 21, 2026
6 checks passed
@nstepien
nstepien deleted the clarity branch October 21, 2026 23:04
nstepien added a commit that referenced this pull request Oct 21, 2026
Stacked on #3967.

Cell events inherit from React's event, but React's `stopPropagation()`
and `preventDefault()` store their state on the object they're called
on. When called on a cell event, they updated the cell event instead of
React's event, so:
- `stopPropagation()` in `onCellClick`, `onCellKeyDown`, or another cell
event handler didn't stop React from calling parent handlers.
- After `preventDefault()`, parent handlers saw `isDefaultPrevented()`
return `false`.

The native event was still updated, so the browser's default action was
prevented.

This predates #3967: cell events used to copy React's event, with the
same result.

Cell events now call these two methods on React's event. The two new
tests failed in all three browsers before the fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
fn: Maybe<(...args: Args) => void>
): Maybe<(...args: Args) => void>;

export function useLatestFunc<Args extends unknown[]>(fn: Maybe<(...args: Args) => void>) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Don't think I fully understand this TS code :)

Comment on lines +104 to +107
startTransition(async () => {
const newRows = await loadMoreRows(50, rows.length);
// state updates after `await` must be wrapped in another transition
startTransition(() => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For my understand, does the isPending flag stay true until both transitions are complete?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes.
The nested startTransition is necessary otherwise React wouldn't know that the nested state update is part of this transition.
https://react.dev/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition

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.

3 participants