-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat(table): 表格排序与筛选相关调整修正 #9216
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
Conversation
1. 匹配 key 值 columnKey 改用 parseDataIndex 使其與預設值設置方式對齊(parseServerDefaultColumnConfig) 2. 封裝排序雙向綁定邏輯
1. 修正 filter 測試項誤放 sort 問題 2. 拆分 sort 測試檔案 3. 新增 sort 本地與服務端同時配置測試項
📝 WalkthroughWalkthrough本次变更主要重构了 ProTable 组件的排序与筛选逻辑,统一了服务端与本地的状态管理和类型定义。API 文档新增了 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ProTable
participant AntdTable
participant Server
User->>ProTable: 操作列头进行排序/筛选
ProTable->>AntdTable: 传递排序/筛选配置
AntdTable-->>ProTable: 返回 onChange (filters, sorter)
ProTable->>ProTable: 使用 getServerFilterResult / getServerSorterResult 解析
ProTable->>Server: 发起带解析参数的请求
Server-->>ProTable: 返回数据
ProTable->>AntdTable: 渲染新数据
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested labels
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 2
🧹 Nitpick comments (13)
src/table/Table.tsx (2)
143-146
: 未使用的变量可以优化
useFilterColumns
被计算但只在onChange
处理器中使用。考虑将其移到使用的地方附近或使用useCallback
优化。- // 需要进行筛选的列 - const useFilterColumns = useMemo(() => { - const _columns: any[] = flattenColumns(columns); - return _columns.filter((column) => !!column.filters); - }, [columns]);在
onChange
处理器中直接计算:onChange: ( changePagination: TablePaginationConfig, filters: Record<string, AntFilterValue | null>, sorter: SorterResult<T> | SorterResult<T>[], extra: TableCurrentDataSource<T>, ) => { rest.onChange?.(changePagination, filters, sorter, extra); + const filterColumns = flattenColumns(columns).filter((column) => !!column.filters); // 传递服务端筛选数据 - const serverFilter = getServerFilterResult(filters, useFilterColumns); + const serverFilter = getServerFilterResult(filters, filterColumns); onFilterChange(omitUndefined(serverFilter));
961-968
: 深度比较可能影响性能每次调用
onSortChange
和onFilterChange
时都使用isEqual
进行深度比较,在数据量大时可能影响性能。考虑使用浅比较或者将比较逻辑移到父组件:
- onSortChange={(sortConfig) => { - if (isEqual(sortConfig, proSort)) return; - setProSort(sortConfig ?? {}); - }} + onSortChange={useCallback((sortConfig) => { + setProSort((prev) => { + const next = sortConfig ?? {}; + return isEqual(prev, next) ? prev : next; + }); + }, [])}src/table/utils/index.ts (3)
234-242
: 优化服务端筛选数据获取逻辑函数逻辑正确,但可以使用更简洁的写法。
export const getServerFilterResult = <T>(filters: Record<string, AntFilterValue | null>, columns: ProColumnType<T>[]) => { // 过滤掉本地筛选的列 - return Object.entries(filters).reduce<Record<string, FilterValue>>((acc, [key, value]) => { - const column = columns.find((column) => parseDataIndex(column.dataIndex) === key); - if(column != null && !isLocaleFilter(column.filters, column.onFilter)) acc[key] = value as FilterValue; - - return acc; - }, {}); + const columnMap = new Map(columns.map(col => [parseDataIndex(col.dataIndex), col])); + return Object.entries(filters).reduce<Record<string, FilterValue>>((acc, [key, value]) => { + const column = columnMap.get(key); + if(column && !isLocaleFilter(column.filters, column.onFilter)) { + acc[key] = value as FilterValue; + } + return acc; + }, {}); }
285-289
: 简化排序键的处理逻辑条件分支可以简化,提高代码可读性。
- if(typeof column.sorter === 'string') { - sort[column.sorter] = column.defaultSortOrder ?? null; - } else { - sort[dataIndex] = column.defaultSortOrder ?? null; - } + const sortKey = typeof column.sorter === 'string' ? column.sorter : dataIndex; + sort[sortKey] = column.defaultSortOrder ?? null;
336-336
: 类型断言可以更安全直接使用
as FilterValue
可能隐藏类型错误。- if(columnFilteredValue !== undefined) return columnFilteredValue as FilterValue; + if(columnFilteredValue !== undefined) { + // 验证类型是否匹配 + return Array.isArray(columnFilteredValue) || columnFilteredValue === null + ? columnFilteredValue as FilterValue + : null; + }tests/table/sorter.test.tsx (8)
3-3
: 移除不必要的引用注释测试文件通常不需要
@vitest/browser/context
的引用注释,除非有特定的 IDE 配置需求。-/// <reference types="@vitest/browser/context" />
69-74
: 优化测试超时配置测试中的超时时间过长(10000ms 和 15000ms)。对于简单的 UI 交互测试,这些超时时间应该可以大幅缩短。
await waitFor( () => { expect(container.querySelector('.ant-table-row')).toBeInTheDocument(); }, - { timeout: 10000 }, + { timeout: 3000 }, );同时建议将测试的整体超时时间从 15000ms 减少到 5000ms:
- }, 15000); + }, 5000);Also applies to: 90-90
89-89
: 增强断言以验证 onChange 参数当前测试只验证了
onChange
被调用的次数,建议同时验证传递给onChange
的排序参数是否正确。- expect(fn).toHaveBeenCalledTimes(4); + expect(fn).toHaveBeenCalledTimes(4); + // 验证最后一次调用的参数 + const lastCall = fn.mock.calls[fn.mock.calls.length - 1]; + expect(lastCall[1]).toBeDefined(); // pagination + expect(lastCall[2]).toBeDefined(); // filters + expect(lastCall[3]).toBeDefined(); // sorter
145-145
: 减少测试超时时间与第一个测试类似,10000ms 的超时时间过长。
- }, 10000); + }, 5000);
236-236
: 优化测试超时配置15000ms 的超时时间对于本地排序测试来说过长。
- }, 15000); + }, 5000);
330-330
: 统一使用简体中文注释注释中使用了繁体中文"透过",建议统一使用简体中文。
- // 验证 fn 有被调用,因为排序是透过服务端进行的 + // 验证 fn 有被调用,因为排序是通过服务端进行的
707-707
: 统一使用简体中文注释注释中混用了繁体中文字符(如"數據"、"獲取"),建议统一使用简体中文以保持一致性。
- // 等待初始數據渲染 + // 等待初始数据渲染- // 獲取排序元素 + // 获取排序元素Also applies to: 785-785, 884-884, 986-986
877-877
: 添加分号保持代码风格一致性return 语句末尾缺少分号。
- return 0 + return 0;Also applies to: 979-979
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
site/components/table/index.md
(1 hunks)src/table/Table.tsx
(8 hunks)src/table/typing.ts
(3 hunks)src/table/utils/genProColumnToColumn.tsx
(4 hunks)src/table/utils/index.ts
(3 hunks)tests/table/filter.test.tsx
(0 hunks)tests/table/sorter.test.tsx
(1 hunks)
💤 Files with no reviewable changes (1)
- tests/table/filter.test.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{tsx,jsx}
📄 CodeRabbit Inference Engine (.cursor/rules/react.mdc)
**/*.{tsx,jsx}
: Use early returns whenever possible to make the code more readable.
Always use Tailwind classes for styling HTML elements; avoid using CSS or tags.
Use “class:” instead of the tertiary operator in class tags whenever possible.
Use descriptive variable and function/const names. Also, event functions should be named with a “handle” prefix, like “handleClick” for onClick and “handleKeyDown” for onKeyDown.
Implement accessibility features on elements. For example, a tag should have a tabindex=“0”, aria-label, on:click, and on:keydown, and similar attributes.
Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.
Files:
src/table/Table.tsx
tests/table/sorter.test.tsx
src/table/utils/genProColumnToColumn.tsx
🧠 Learnings (7)
📚 Learning: applies to **/*.{tsx,jsx} : use consts instead of functions, for example, “const toggle = () =>”. al...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T09:28:05.125Z
Learning: Applies to **/*.{tsx,jsx} : Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.
Applied to files:
src/table/Table.tsx
src/table/utils/index.ts
📚 Learning: applies to test/**/* : utilize playwright fixtures (e.g., `test`, `page`, `expect`) to maintain test...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Utilize Playwright fixtures (e.g., `test`, `page`, `expect`) to maintain test isolation and consistency.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : use `expect` matchers for assertions (`toequal`, `tocontain`, `tobetruthy`, `...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) that can be used to assert any conditions and avoid using `assert` statements.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : add jsdoc comments to describe the purpose of helper functions and reusable l...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Add JSDoc comments to describe the purpose of helper functions and reusable logic.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : use `page.getbytestid` whenever `data-testid` is defined on an element or con...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Use `page.getByTestId` whenever `data-testid` is defined on an element or container.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : prefer to use web-first assertions (`tobevisible`, `tohavetext`, etc.) whenev...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Prefer to use web-first assertions (`toBeVisible`, `toHaveText`, etc.) whenever possible.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : use `page.waitfor` with specific conditions or events to wait for elements or...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Use `page.waitFor` with specific conditions or events to wait for elements or states.
Applied to files:
tests/table/sorter.test.tsx
🧬 Code Graph Analysis (2)
tests/table/sorter.test.tsx (2)
tests/table/demo.tsx (2)
getFetchData
(181-181)columns
(44-179)src/table/typing.ts (2)
ActionType
(458-461)ProColumns
(178-181)
src/table/utils/genProColumnToColumn.tsx (2)
src/table/typing.ts (1)
FilterValue
(79-79)src/table/utils/index.ts (2)
parseProFilteredValue
(329-349)parseProSortOrder
(301-321)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: build
- GitHub Check: build
- GitHub Check: build (20.x, ubuntu-latest)
🔇 Additional comments (10)
site/components/table/index.md (1)
252-252
: 文档更新符合预期!新增的
sorter
属性说明清晰,支持字符串类型来覆盖请求时的字段名称,这与代码实现保持一致。src/table/utils/genProColumnToColumn.tsx (3)
32-32
: 类型定义更加精确!将
proFilter
的类型从通用的 Record 更新为具体的FilterValue
类型,提高了类型安全性。
114-115
: 使用工具函数提升代码可维护性!使用
parseProFilteredValue
和parseProSortOrder
工具函数替代内联逻辑,集中化了服务端与本地筛选/排序的处理逻辑。
56-57
: 已验证:genProColumnToColumn 的所有调用均显式传递了 proFilter
- 在 src/table/Table.tsx 第 737 行调用时,参数列表中包含 proFilter 和 proSort,无遗漏。
src/table/typing.ts (2)
75-79
: FilterValue 类型定义合理!新增的
FilterValue
类型明确定义了筛选参数的格式,与 Ant Design 的类型区分开来,避免了类型混淆。
81-89
: ProSorter 类型扩展功能完善!
ProSorter<T>
类型支持字符串来覆盖请求字段名,这是一个很好的功能扩展,使得前后端字段映射更加灵活。src/table/Table.tsx (1)
487-495
: 状态初始化逻辑清晰!使用
parseServerDefaultColumnConfig
统一解析默认的服务端筛选和排序配置,提高了代码的可维护性。tests/table/sorter.test.tsx (3)
337-441
: 测试实现良好!这个测试很好地覆盖了使用
actionRef.reset()
重置排序到默认状态的功能,这正是 PR 目标中提到的关键修复之一。
443-531
: 字符串排序参数测试实现优秀!这个测试很好地验证了新增的字符串排序器功能(PR 中提到的 issue #2376),确保了服务端排序时能正确传递自定义的排序字段名。
631-1017
: 多列排序测试覆盖全面!这组测试很好地覆盖了 PR 中提到的多列排序问题(issue #9143),包括:
- 本地多列排序
- 服务端多列排序
- 混合模式(本地+服务端)排序
- 不同优先级的排序处理
测试结构清晰,场景覆盖完整。
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.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/table/utils/index.ts (1)
194-207
: 递归调用已正确收集结果该问题已在当前版本中修复,递归调用的结果已通过扩展运算符正确收集到
_columns
数组中。tests/table/sorter.test.tsx (1)
533-629
: 类型问题已修复useState 的类型定义已正确更新为
SortOrder | null
,支持 null 值赋值。
🧹 Nitpick comments (5)
src/table/utils/index.ts (2)
234-242
: 建议使用严格相等检查在第 238 行,建议使用严格相等检查来提高代码可读性:
- if(column != null && !isLocaleFilter(column.filters, column.onFilter)) acc[key] = value as FilterValue; + if(column !== null && column !== undefined && !isLocaleFilter(column.filters, column.onFilter)) acc[key] = value as FilterValue;
249-262
: 建议使用严格相等检查并优化类型断言在第 254 和 257 行,建议使用更明确的条件判断:
- if(sorter != null && isLocaleSorter<T>(sorter)) return acc; + if(sorter !== null && sorter !== undefined && isLocaleSorter<T>(sorter)) return acc; - if(sortKey != null) acc[sortKey] = item.order; + if(sortKey !== null && sortKey !== undefined) acc[sortKey] = item.order;tests/table/sorter.test.tsx (3)
22-91
: 建议减少测试超时时间15 秒的超时时间过长,正常的表格交互不应该需要这么长时间。建议减少到 5000ms。
- }, 15000); + }, 5000);
639-648
: 建议提取组件属性接口定义为了提高代码可读性和类型安全性,建议为 TestComponent 的属性定义一个独立的接口:
interface TestComponentProps { columns: ProColumns<DataSource, "text">[]; dataSource?: DataSource[]; request?: (params: any, sort: any) => Promise<{ total: number; success: boolean; data: DataSource[] }>; } const TestComponent = ({ columns, dataSource, request }: TestComponentProps) => ( // ... );
1-1018
: 建议统一注释语言测试文件中混合使用了中英文注释(如第 707、785 行的中文注释与其他英文代码),建议统一使用一种语言以提高代码一致性。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/table/utils/index.ts
(3 hunks)tests/table/sorter.test.tsx
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{tsx,jsx}
📄 CodeRabbit Inference Engine (.cursor/rules/react.mdc)
**/*.{tsx,jsx}
: Use early returns whenever possible to make the code more readable.
Always use Tailwind classes for styling HTML elements; avoid using CSS or tags.
Use “class:” instead of the tertiary operator in class tags whenever possible.
Use descriptive variable and function/const names. Also, event functions should be named with a “handle” prefix, like “handleClick” for onClick and “handleKeyDown” for onKeyDown.
Implement accessibility features on elements. For example, a tag should have a tabindex=“0”, aria-label, on:click, and on:keydown, and similar attributes.
Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.
Files:
tests/table/sorter.test.tsx
🧠 Learnings (7)
📚 Learning: applies to **/*.{tsx,jsx} : use consts instead of functions, for example, “const toggle = () =>”. al...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T09:28:05.125Z
Learning: Applies to **/*.{tsx,jsx} : Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.
Applied to files:
src/table/utils/index.ts
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : utilize playwright fixtures (e.g., `test`, `page`, `expect`) to maintain test...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Utilize Playwright fixtures (e.g., `test`, `page`, `expect`) to maintain test isolation and consistency.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : use `expect` matchers for assertions (`toequal`, `tocontain`, `tobetruthy`, `...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) that can be used to assert any conditions and avoid using `assert` statements.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : add jsdoc comments to describe the purpose of helper functions and reusable l...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Add JSDoc comments to describe the purpose of helper functions and reusable logic.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : use `page.getbytestid` whenever `data-testid` is defined on an element or con...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Use `page.getByTestId` whenever `data-testid` is defined on an element or container.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : prefer to use web-first assertions (`tobevisible`, `tohavetext`, etc.) whenev...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Prefer to use web-first assertions (`toBeVisible`, `toHaveText`, etc.) whenever possible.
Applied to files:
tests/table/sorter.test.tsx
📚 Learning: applies to test/**/* : use `page.waitfor` with specific conditions or events to wait for elements or...
Learnt from: CR
PR: ant-design/pro-components#0
File: .cursor/rules/test.mdc:0-0
Timestamp: 2025-08-01T09:28:29.050Z
Learning: Applies to test/**/* : Use `page.waitFor` with specific conditions or events to wait for elements or states.
Applied to files:
tests/table/sorter.test.tsx
🧬 Code Graph Analysis (1)
src/table/utils/index.ts (1)
tests/table/demo.tsx (1)
columns
(44-179)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: build
- GitHub Check: build
- GitHub Check: build (20.x, ubuntu-latest)
- GitHub Check: Analyze (javascript)
🔇 Additional comments (6)
src/table/utils/index.ts (5)
215-217
: 本地筛选判断逻辑正确函数正确判断了是否为本地筛选,当同时存在
filters
和onFilter
时返回 true。
224-226
: 本地排序判断逻辑完善正确识别了本地排序的两种情况:直接的比较函数或包含 compare 属性的对象。
268-293
: 服务端默认配置解析逻辑完善函数正确处理了服务端排序和筛选的默认配置,特别是对字符串类型 sorter 的特殊处理很合理。
301-321
: 排序值双向绑定解析逻辑清晰函数正确实现了排序值的解析优先级:
- 优先使用用户明确设置的 sortOrder
- 本地排序不使用 proSort 中的值
- 服务端排序正确处理字符串类型的 sorter
329-349
: 筛选值双向绑定解析逻辑一致函数与
parseProSortOrder
保持了一致的实现模式,正确处理了筛选值的解析优先级。tests/table/sorter.test.tsx (1)
650-1017
: 多列排序测试覆盖全面测试用例很好地覆盖了多种排序场景:
- 多列本地排序
- 多列服务端排序
- 本地与服务端混合排序
- 排序优先级处理
测试实现质量高,异步操作处理得当。
针对排序(sort)与筛选(filter)做了以下逻辑整理
Summary by CodeRabbit
新功能
sorter
属性,支持字符串类型以指定请求排序字段。重构
类型完善
文档
sorter
属性说明及类型。测试