-
-
Notifications
You must be signed in to change notification settings - Fork 622
fix: duplicate unique identifiers in MeasureRow column headers #1378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import * as React from 'react'; | ||
| import ResizeObserver from '@rc-component/resize-observer'; | ||
| import useLayoutEffect from '@rc-component/util/lib/hooks/useLayoutEffect'; | ||
| import { cleanMeasureRowAttributes } from '../utils/measureUtil'; | ||
|
|
||
| export interface MeasureCellProps { | ||
| columnKey: React.Key; | ||
|
|
@@ -12,20 +13,27 @@ const MeasureCell: React.FC<MeasureCellProps> = props => { | |
| const { columnKey, onColumnResize, title } = props; | ||
|
|
||
| const cellRef = React.useRef<HTMLTableCellElement>(null); | ||
| const contentRef = React.useRef<HTMLDivElement>(null); | ||
|
|
||
| useLayoutEffect(() => { | ||
| if (cellRef.current) { | ||
| onColumnResize(columnKey, cellRef.current.offsetWidth); | ||
| } | ||
| }, []); | ||
|
|
||
| if (contentRef.current) { | ||
| cleanMeasureRowAttributes(contentRef.current); | ||
| } | ||
| }, [title, columnKey, onColumnResize]); | ||
|
Comment on lines
+22
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 清理逻辑不完整,且存在性能隐患。 存在以下问题:
建议修复方案:
export function cleanMeasureRowAttributes(element: HTMLElement): void {
if (!element) return;
// 清理元素本身的属性
FILTERED_ATTRIBUTES.forEach(attr => {
element.removeAttribute(attr);
});
// 清理所有后代元素
const allElements = element.querySelectorAll('*');
allElements.forEach(el => {
FILTERED_ATTRIBUTES.forEach(attr => {
el.removeAttribute(attr);
});
});
}
🤖 Prompt for AI Agents |
||
|
|
||
| return ( | ||
| <ResizeObserver data={columnKey}> | ||
| <td | ||
| ref={cellRef} | ||
| style={{ paddingTop: 0, paddingBottom: 0, borderTop: 0, borderBottom: 0, height: 0 }} | ||
| > | ||
| <div style={{ height: 0, overflow: 'hidden', fontWeight: 'bold' }}>{title || '\xa0'}</div> | ||
| <div ref={contentRef} style={{ height: 0, overflow: 'hidden', fontWeight: 'bold' }}> | ||
| {title || '\xa0'} | ||
| </div> | ||
| </td> | ||
| </ResizeObserver> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /** | ||
| * Attributes that should be removed from measure row DOM to avoid conflicts | ||
| */ | ||
| const FILTERED_ATTRIBUTES = [ | ||
| // Unique identifiers that shouldn't be duplicated in DOM | ||
| 'id', | ||
| 'data-testid', | ||
| 'data-test-id', | ||
| 'data-cy', // Cypress | ||
| 'data-qa', | ||
| 'data-automation-id', | ||
| 'data-id', | ||
| 'data-key', | ||
| ] as const; | ||
|
|
||
| /** | ||
| * Remove all ID and test attributes from DOM element and its descendants | ||
| * This ensures the measure row complies with HTML spec (no duplicate IDs) | ||
| * and works with custom components whose internal DOM we cannot control at React level | ||
| * @param element - The DOM element to clean | ||
| */ | ||
| export function cleanMeasureRowAttributes(element: HTMLElement): void { | ||
| if (!element) return; | ||
|
|
||
| const allElements = element.querySelectorAll('*'); | ||
| allElements.forEach(el => { | ||
| FILTERED_ATTRIBUTES.forEach(attr => { | ||
| el.removeAttribute(attr); | ||
| }); | ||
| }); | ||
|
Comment on lines
+25
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
|
Comment on lines
+22
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 函数未清理根元素本身的属性。
应用此修复: export function cleanMeasureRowAttributes(element: HTMLElement): void {
if (!element) return;
+ // Remove attributes from the element itself
+ FILTERED_ATTRIBUTES.forEach(attr => {
+ element.removeAttribute(attr);
+ });
+
+ // Remove attributes from all descendants
const allElements = element.querySelectorAll('*');
allElements.forEach(el => {
FILTERED_ATTRIBUTES.forEach(attr => {
el.removeAttribute(attr);
});
});
}🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果里面有异步逻辑,比如依赖里面的 id 或者其他属性的做 dom 操作,这样移除后会可能会引发报错。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果真的依赖id做操作,操作显示的那个dom才是正常的吧;这个dom只是用于测量宽度,实际不可见,反而不去除这些属性就可能有两个id一样的dom