Skip to content

Conversation

cactuser-Lu
Copy link
Contributor

@cactuser-Lu cactuser-Lu commented Oct 9, 2025

问题描述

在使用 rc-table 时,当列标题包含 iddata-testid 等唯一标识符时,由于 MeasureRow 会复制列标题内容,会导致 DOM 中出现重复的标识符,这违反了 HTML 规范并可能影响测试和可访问性。

fix ant-design/ant-design#55244
close #1375

问题示例

const columns = [
  {
    title: <div id="unique-header" data-testid="my-header">Column Title</div>,
    dataIndex: 'col1',
    key: 'col1',
  }
];

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- 新增功能
  - 引入标题预处理与清理机制,默认对复杂或自定义标题内容进行深度清理,提升渲染一致性。

- 修复
  - 修复度量行标题在包含自定义内容或复杂嵌套时的渲染不一致问题,提升稳定性与可预期性。

- 重构
  - 将标题处理整合为统一流程,内部行为调整但对外接口无变更。
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Copy link

vercel bot commented Oct 9, 2025

Someone is attempting to deploy a commit to the React Component Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

Summary of Changes

Hello @cactuser-Lu, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical DOM validation issue within the rc-table component. Previously, the MeasureRow would inadvertently clone column header elements, leading to duplicate unique identifiers and other conflicting attributes in the rendered DOM. The fix introduces a robust prop filtering mechanism that sanitizes column titles, ensuring that only safe and non-conflicting attributes are present in the measurement row, thereby maintaining HTML validity and improving compatibility with testing and accessibility tools.

Highlights

  • Fix Duplicate Identifiers: Addresses an issue where MeasureRow in rc-table would duplicate unique identifiers (like id and data-testid) in column headers, leading to invalid HTML and potential problems for testing and accessibility.
  • New Utility for Prop Filtering: Introduces a new utility file, src/utils/measureUtil.ts, which contains functions to filter out problematic props from React elements used in the measurement row.
  • Sanitized Column Titles: The MeasureRow component now utilizes the new prepareMeasureTitle utility function to process column titles, ensuring that unique identifiers, event handlers, accessibility props, and form-related props are removed before rendering.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

coderabbitai bot commented Oct 9, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

将 MeasureRow 中内联的标题清洗与克隆逻辑替换为对外工具方法 prepareMeasureTitle;新增 src/utils/measureUtil.ts 提供属性过滤与标题预处理,MeasureRow 将处理后的标题通过 titleForMeasure 传给 MeasureCell,未修改公共 API。

Changes

Cohort / File(s) Summary
Measure 行渲染改造
src/Body/MeasureRow.tsx
移除内联的 React 元素校验/clone/ref 处理;引入并调用 prepareMeasureTitle 对列标题进行预处理;把处理后的标题通过 titleForMeasure 传给 MeasureCell
测量标题与属性过滤工具
src/utils/measureUtil.ts
新增 filterMeasureProps(可递归)以克隆并过滤元素 props(移除 testid、data-、事件、aria、form 等可能冲突的属性);新增 prepareMeasureTitleReactNode 执行深度清洗(元素则过滤、非元素原样返回);导出上述方法。

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor React
  participant MeasureRow
  participant measureUtil as prepareMeasureTitle
  participant MeasureCell

  React->>MeasureRow: render(columns)
  MeasureRow->>measureUtil: prepareMeasureTitle(rawTitle)
  measureUtil-->>MeasureRow: sanitizedTitle
  MeasureRow->>MeasureCell: render(titleForMeasure = sanitizedTitle)
  MeasureCell-->>React: measured output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

小兔量行轻又巧,
标题洗净不留毛。
testid 不重影藏手,
表格整洁风自笑。
又跳又叹代码好,🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed PR 标题准确地反映了主要更改——修复 MeasureRow 列头中重复唯一标识符的问题,并与代码中新添加的属性过滤逻辑保持一致。标题简洁明确,易于历史记录检索。
Linked Issues Check ✅ Passed 代码通过在 MeasureRow 中使用 prepareMeasureTitle 并过滤 id、data-testid 等属性,解决了重复复制列头标识符的问题,完全满足了 issue #55244 中的预期行为。
Out of Scope Changes Check ✅ Passed 所有更改均针对 MeasureRow 中复制属性问题进行处理,新增的 measureUtil.ts 工具模块用于属性过滤,与 issue 目标高度一致,未引入无关功能。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

这个 PR 旨在解决 MeasureRow 复制列标题时,由于 id 等唯一标识符重复导致的问题。通过创建一个新的工具函数 prepareMeasureTitle 来过滤掉这些可能引起冲突的属性,这个方案是合理的。代码实现很清晰,递归地处理了子元素,并且过滤的属性列表也比较全面。

我发现一个新的潜在问题,新的实现似乎遗漏了清除 ref 属性的逻辑,这在之前的代码中是存在的。如果原始的标题元素带有 ref,复制后可能会导致 React 警告或非预期的行为。我在 src/utils/measureUtil.ts 文件中提出了具体的修改建议以修复此问题。

Comment on lines 57 to 64
FILTERED_PROPS.forEach(prop => {
filteredProps[prop] = undefined;
});

// Recursively filter children if deep filtering is enabled
if (deep && filteredProps.children) {
filteredProps.children = filterMeasureChildren(filteredProps.children);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

此前的 MeasureRow 实现中,通过 React.cloneElement(rawTitle, { ref: null }) 显式地将 ref 置空,以避免在测量用的副本元素上附加 ref。当前的 filterMeasureProps 实现虽然过滤了许多其他属性,但遗漏了对 ref 的处理。如果 title 组件上附加了 ref,这可能会导致非预期的副作用或 React 警告,算是一个功能上的回归。

建议在此处将 ref 也置为 null,以保持原有逻辑并增强健壮性。

  FILTERED_PROPS.forEach(prop => {
    filteredProps[prop] = undefined;
  });

  // Nullify ref to avoid warnings and conflicts
  filteredProps.ref = null;

  // Recursively filter children if deep filtering is enabled
  if (deep && filteredProps.children) {
    filteredProps.children = filterMeasureChildren(filteredProps.children);
  }

@cactuser-Lu cactuser-Lu closed this Oct 9, 2025
Copy link

codecov bot commented Oct 9, 2025

Codecov Report

❌ Patch coverage is 96.72131% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.10%. Comparing base (057acc8) to head (a8636fb).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/utils/measureUtil.ts 96.61% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1376   +/-   ##
=======================================
  Coverage   96.09%   96.10%           
=======================================
  Files          57       58    +1     
  Lines        3434     3492   +58     
  Branches      632      640    +8     
=======================================
+ Hits         3300     3356   +56     
- Misses        129      131    +2     
  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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cactuser-Lu cactuser-Lu reopened this Oct 9, 2025
@afc163 afc163 merged commit c58ee99 into react-component:master Oct 9, 2025
7 of 8 checks passed
afc163 pushed a commit that referenced this pull request Oct 9, 2025
@afc163
Copy link
Member

afc163 commented Oct 9, 2025

  const columns = [
    {
      title: <DashboardColumnTitle title="Patient" testId="patient" />,
      dataIndex: "patient",
      key: "patient",
      width: "25%",
    },

递归解决不了 DashboardColumnTitle 里面的节点有 id 和 data-* 属性的这种写法。我先回滚。

@afc163
Copy link
Member

afc163 commented Oct 9, 2025

可能要用 React.createProtal + dom 操作才有可能彻底解决。

@cactuser-Lu
Copy link
Contributor Author

使用useLayoutEffect在渲染前清理可行吗

@cactuser-Lu
Copy link
Contributor Author

可能要用 React.createProtal + dom 操作才有可能彻底解决。

我又新提了一个,应该可以了

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.

MeasureRow is duplicating testid in Table

2 participants