Skip to content

Conversation

Linkodt
Copy link
Contributor

@Linkodt Linkodt commented Sep 23, 2025

@afc163 @crazyair 大佬们看看呢?
可以在 useLayoutEffect 内通过 getClientRects 获取header 宽度。

当前碰到的问题:

  1. 这种合并表头的 列没办法一一对应上。
image

Summary by CodeRabbit

  • 新增功能

  • Bug 修复

    • 表格列宽与表头实时同步,修复首次渲染与调整大小时的单元格/表头错位与闪烁问题。
  • 样式

    • 单元格宽度基于表头自动适配,提升表格布局一致性与可读性。

Copy link

coderabbitai bot commented Sep 23, 2025

Walkthrough

在 MeasureCell 增加可选的 columnIndex 属性并移除 title。MeasureCell 在布局时通过 columnIndex 从表头 DOM 读取对应列宽并设置自身宽度,同时保留挂载时触发 onColumnResize。MeasureRow 改为计算 columnIndex 并传给 MeasureCell,停止传递 title。

Changes

Cohort / File(s) Summary
Body measure components
src/Body/MeasureCell.tsx, src/Body/MeasureRow.tsx
MeasureCell: 新增 columnIndex?: number,移除 title?: React.ReactNode;在布局中依据 columnIndex 从表头 DOM 读取宽度并设置内部 div 宽度;仍在挂载时调用 onColumnResize。MeasureRow: 通过 findIndex 计算 columnIndex,传给 MeasureCell,停止传递 title

Sequence Diagram(s)

sequenceDiagram
  participant Row as MeasureRow
  participant Cell as MeasureCell
  participant DOM as Header DOM
  participant CB as onColumnResize

  Row->>Cell: render({ columnIndex })
  Note over Cell: 初始渲染

  alt columnIndex 已定义
    Cell->>DOM: 查询对应表头单元格宽度
    DOM-->>Cell: width(px)
    Cell->>Cell: 设置内部容器样式 width
  else 未定义
    Cell->>Cell: 使用自身测量宽度
  end

  Cell->>CB: onMount: onColumnResize(offsetWidth)
  Note over Cell: 维持原有挂载回调
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • afc163
  • zombieJ

Poem

小兔量尺轻轻摆,
表头取宽不出差。
列序一指宽自来,
旧日标题轻挥bye。
挂载仍把尺寸晒,
表格齐整蹦蹦迈。 🐇📏

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 标题 "[WIP]get columnHeader's real width" 明确反映了该 PR 的主要目的,即获取列头的实际宽度,且与变更中在布局阶段读取并使用列头宽度的实现一致。标题简短且能让审阅者快速理解主要改动方向。唯一的小问题是开头的 "[WIP]" 为工作进行中标记,会带来少量噪音但不影响可识别性。
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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

Summary of Changes

Hello @Linkodt, 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!

此拉取请求旨在解决表格列头宽度测量不准确的问题,特别是在存在合并表头的情况下。通过引入一种新的宽度测量机制,即利用 useLayoutEffect 和 DOM API (getClientRects) 来获取表头单元格的真实渲染宽度,从而确保表格布局的准确性。这一改进使得表格能够更精确地处理复杂的列头结构。

Highlights

  • 优化列宽测量: 引入 columnIndex 属性,并在 useLayoutEffect 中通过 document.querySelectorAllgetClientRects 获取表头单元格的实际渲染宽度,以解决合并表头等场景下的宽度测量不准确问题。
  • MeasureCell 组件更新: 移除了 title 属性,新增了 columnIndex 属性,并使用获取到的实际宽度来设置内部 div 的样式,确保宽度显示正确。
  • MeasureRow 组件更新: 在渲染 MeasureCell 时,不再传递 title 属性,而是计算并传递 columnIndex
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

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.

@Linkodt Linkodt changed the title get columnHeader's real width [WIP]get columnHeader's real width Sep 23, 2025
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 旨在通过获取表头单元格的实际宽度来解决复杂表头(如合并表头)下的列宽测量问题。这是一个很好的思路,但目前的实现存在一些问题,可能导致在某些情况下无法正常工作或代码脆弱。

我的主要反馈集中在 MeasureCell.tsx 中:

  1. 硬编码的 CSS 类名: 直接使用了 .rc-table-thead.rc-table-cell,这会使得在自定义 prefixCls 时组件失效。
  2. 不够健壮的 DOM 查询: querySelectorAll 的选择器对于分组/合并表头不够精确,可能导致获取到错误的单元格。
  3. useLayoutEffect 依赖项缺失: useLayoutEffect 的依赖数组为空,这会导致 effect 只在组件挂载时运行一次,无法响应 props 的变化。

我提供了一些具体的代码建议来修复这些问题,主要是通过传递 prefixCls 并使用更精确的 DOM 选择器来增强代码的健壮性和正确性。

Comment on lines 40 to 45
<MeasureCell
key={columnKey}
columnIndex={columnIndex}
columnKey={columnKey}
onColumnResize={onColumnResize}
title={column?.title}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

high

为了让 MeasureCell 能够构建正确的 DOM 选择器,而不是使用硬编码的类名,建议将 prefixCls 属性传递给它。这能显著提高 MeasureCell 组件的健壮性。

            <MeasureCell
              key={columnKey}
              prefixCls={prefixCls}
              columnIndex={columnIndex}
              columnKey={columnKey}
              onColumnResize={onColumnResize}
            />

Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Body/MeasureCell.tsx (1)

16-27: 修正测量与上报逻辑:限定作用域到当前表、避免首次 0 宽度上报,并处理 columnIndex = -1

当前用 document.querySelectorAll 跨文档查询且硬编码类名,可能跨多表实例误读;同时在 setWidth 之前调用 onColumnResize,首次很容易上报 0 宽度;还未过滤 findIndex 返回 -1 的情况。建议:

  • 以当前单元格为起点,限定到最近的 table 再查找最后一行表头(叶子列)。
  • 检查 columnIndex >= 0。
  • 先测量再上报,或依赖 ResizeObserver 的变更回调;下方示例选择“测量后立即上报”,并添加合理依赖。
-  useLayoutEffect(() => {
-    if (columnIndex !== undefined) {
-      setWidth(
-        document
-          .querySelectorAll('.rc-table-thead >tr > .rc-table-cell')
-          [columnIndex]?.getClientRects()[0].width || 0,
-      );
-    }
-    if (cellRef.current) {
-      onColumnResize(columnKey, cellRef.current.offsetWidth);
-    }
-  }, []);
+  useLayoutEffect(() => {
+    if (cellRef.current && columnIndex != null && columnIndex >= 0) {
+      const table = cellRef.current.closest('table');
+      const headerCells = table?.querySelectorAll(
+        `.${prefixCls}-thead > tr:last-child > .${prefixCls}-cell`,
+      );
+      const nextWidth =
+        headerCells?.[columnIndex]?.getBoundingClientRect().width || 0;
+      setWidth(nextWidth);
+      // 直接使用表头测得宽度上报,避免首次 0 宽度
+      onColumnResize(columnKey, nextWidth);
+    }
+  }, [columnIndex, prefixCls]);
🧹 Nitpick comments (2)
src/Body/MeasureCell.tsx (2)

5-9: 不要硬编码 rc-table 类名;通过 props 传入 prefixCls 以定位当前表头

为支持自定义前缀及多表场景,需要将 prefixCls 传入 MeasureCell 并用于选择器拼装。

 export interface MeasureCellProps {
   columnKey: React.Key;
   onColumnResize: (key: React.Key, width: number) => void;
-  columnIndex?: number;
+  columnIndex?: number;
+  prefixCls: string;
 }
 
 const MeasureCell: React.FC<MeasureCellProps> = props => {
-  const { columnKey, onColumnResize, columnIndex } = props;
+  const { columnKey, onColumnResize, columnIndex, prefixCls } = props;
   const [width, setWidth] = React.useState(0);

Also applies to: 12-13


35-37: 去掉 fontWeight,减少不必要的样式干扰

测量已直接使用表头宽度,内部占位无需加粗,避免潜在的布局差异。

-        <div style={{ height: 0, overflow: 'hidden', fontWeight: 'bold', width: `${width}px` }}>
+        <div style={{ height: 0, overflow: 'hidden', width: `${width}px` }}>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a887d56 and 6434e7e.

📒 Files selected for processing (2)
  • src/Body/MeasureCell.tsx (2 hunks)
  • src/Body/MeasureRow.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/Body/MeasureRow.tsx (1)
tests/FixedColumn-IE.spec.jsx (1)
  • columns (27-40)

Comment on lines 37 to 45
{columnsKey.map(columnKey => {
const column = columns.find(col => col.key === columnKey);
const columnIndex = columns.findIndex(col => col.key === columnKey);
return (
<MeasureCell
key={columnKey}
columnIndex={columnIndex}
columnKey={columnKey}
onColumnResize={onColumnResize}
title={column?.title}
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

findIndex 容易失配(列 key 可能缺失或规则不同),直接使用 map 的 index 作为列序更稳,并下传 prefixCls

当列未显式设置 key 或内部生成规则不同,findIndex 可能返回 -1,导致测量失败。使用遍历索引与表头叶子列顺序一致,更可靠。

-        {columnsKey.map(columnKey => {
-          const columnIndex = columns.findIndex(col => col.key === columnKey);
-          return (
-            <MeasureCell
-              key={columnKey}
-              columnIndex={columnIndex}
-              columnKey={columnKey}
-              onColumnResize={onColumnResize}
-            />
-          );
-        })}
+        {columnsKey.map((columnKey, columnIndex) => (
+          <MeasureCell
+            key={columnKey}
+            columnIndex={columnIndex}
+            prefixCls={prefixCls}
+            columnKey={columnKey}
+            onColumnResize={onColumnResize}
+          />
+        ))}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{columnsKey.map(columnKey => {
const column = columns.find(col => col.key === columnKey);
const columnIndex = columns.findIndex(col => col.key === columnKey);
return (
<MeasureCell
key={columnKey}
columnIndex={columnIndex}
columnKey={columnKey}
onColumnResize={onColumnResize}
title={column?.title}
/>
{columnsKey.map((columnKey, columnIndex) => (
<MeasureCell
key={columnKey}
columnIndex={columnIndex}
prefixCls={prefixCls}
columnKey={columnKey}
onColumnResize={onColumnResize}
/>
))}
🤖 Prompt for AI Agents
In src/Body/MeasureRow.tsx around lines 37 to 45, using columns.findIndex(col =>
col.key === columnKey) can return -1 when keys are missing or differ; change to
use the map iteration index (the second argument of map) as the stable
columnIndex to match header leaf order, and pass the component's prefixCls down
to MeasureCell (add prefixCls={prefixCls}) so styling/namespace is preserved.
Ensure you replace columnIndex assignment with the map index, remove reliance on
findIndex, and include prefixCls in the MeasureCell props.

Copy link

vercel bot commented Sep 23, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
table Ready Ready Preview Comment Sep 23, 2025 4:03pm

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.

2 participants