Skip to content

React project health#9507

Merged
chenshuai2144 merged 8 commits intomasterfrom
cursor/react-project-health-bde8
Feb 26, 2026
Merged

React project health#9507
chenshuai2144 merged 8 commits intomasterfrom
cursor/react-project-health-bde8

Conversation

@chenshuai2144
Copy link
Contributor

@chenshuai2144 chenshuai2144 commented Feb 26, 2026

Fixes all 16 react-doctor errors to improve project health score from 79 to 96.

This PR addresses missing alt attributes, incorrect Hook usage in _useEditableDataSource, derived state in useEffect, and missing key attributes in lists.


Open in Web Open in Cursor 

Summary by CodeRabbit

发布说明

  • 错误修复

    • 为多处图片补充 alt="" 属性,提升无障碍兼容性。
  • 新功能

    • LightFilter 新增可选 initialValues,便于初始化筛选状态。
  • 改进

    • 增强键盘导航:菜单项、标题和分组支持通过 Enter/Space 激活。
    • 简化可编辑表格的编辑流程,移除部分复杂插入场景。
    • 优化布局组件的加载状态处理,提升加载流程一致性与稳定性。

- LoginForm/LoginFormPage: 为 logo  添加  属性
- ProLayout: 背景图  添加 ,JSDoc 示例补充
- ProLayout: 将 useEffect 中的派生状态改为渲染时推导 menuLoading
- LightFilter: 使用 key 重置 moreValues,移除 useEffect 派生状态
- SearchSelect: 使用 useControlledState 替代 useState+useEffect 派生
- EditableTable: 移除未使用的 _useEditableDataSource 及相关死代码
- FormItem/Group: 为隐藏区域 div 添加 key
- demos/tests: 为 img 添加 alt,为 SearchInput 添加 key

react-doctor 评分: 79 → 96

Co-authored-by: 陈帅 <[email protected]>
@cursor
Copy link

cursor bot commented Feb 26, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

本次变更主要改进可访问性与键盘交互(为图片添加 alt、将若干 a/div 改为可聚焦的 button 或添加 role="button"/tabIndex/onKeyDown),重构部分组件的受控状态管理,并移除 EditableTable 中的嵌套行/分页插入逻辑。

Changes

Cohort / File(s) Summary
演示与测试:可访问性与键盘交互
demos/layout/appList-group-simple.tsx, demos/layout/base.tsx, demos/layout/topMode.tsx, tests/layout/index.test.tsx, tests/.../snapshot-*.html
为若干 img 添加 alt="";将交互容器替换或增强为可聚焦的 button 或带 role="button"/tabIndex={0} 且支持 onKeyDown(Enter/Space 触发);更新相应快照。
表单布局与项:键盘交互与渲染优化
src/form/components/FormItem/Group/index.tsx, src/form/layouts/LightFilter/index.tsx, src/form/layouts/LoginForm/index.tsx, src/form/layouts/LoginFormPage/index.tsx
Group 标题增加可聚焦与键盘切换支持(role/tabIndex/onKeyDown);extra 包裹为 role="presentation";LightFilter 重构 collapse 标签渲染、移除同步 effect、添加 initialValues prop;LoginForm 相关在 logo 为字符串时为 <img> 添加 alt=""
Select 组件:受控状态重构
src/field/components/Select/SearchSelect/index.tsx
将内部 searchValueuseState 切换为 useControlledState(支持受控 props 与 default),移除同步 effect,简化受控/非受控管理。
布局:菜单加载状态重构与可访问性小改动
src/layout/ProLayout.tsx
为示例 logo 与背景图添加 alt="" 并改进 key 策略;引入 menuLoadingState 与稳定的 menuOnLoadingChange(useRefFunction),在数据请求前后调用该回调并调整与 SWR 的加载推导逻辑,移除旧的本地 loading 同步 effect。
表格:EditableTable 功能移除
src/table/components/EditableTable/index.tsx
移除与嵌套行插入和分页插入相关的导入与实现(helper 与数据增强逻辑被删),不再支持嵌套/分页插入路径,简化编辑表格的插入流程。

Sequence Diagram(s)

sequenceDiagram
    participant ProLayout as ProLayout
    participant MenuRequest as Menu.request
    participant SWR as SWR
    ProLayout->>ProLayout: menuOnLoadingChange(rgba(0,128,0,0.5)) true
    ProLayout->>MenuRequest: 发起 menu.request()
    MenuRequest->>SWR: 触发 isValidating
    MenuRequest-->>ProLayout: 返回数据 / finally
    ProLayout->>ProLayout: menuOnLoadingChange(rgba(255,0,0,0.5)) false
    Note right of SWR: menuLoading = menu?.loading ?? (menu?.request ? isValidating : menuLoadingState)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • ant-design/pro-components#9419 — 与 FormItem Group 组件中键盘可访问性/折叠回调稳定化存在代码级交叉(均修改 group 折叠行为相关实现)。

Poem

🐰 我是小兔子,敲键来庆贺,
图片有了 alt,标题能被按下,
state 更受控,逻辑被精简,
表格轻了身,键盘也能跳,
我在草地上为可访问鼓掌!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive 标题「React project health」过于宽泛,未能清晰反映变更的主要内容。虽然PR描述表明这是为了修复16个react-doctor错误,但标题本身不够具体,无法让扫描历史的开发者理解具体改动。 建议将标题改为更具体的表述,如「Fix react-doctor errors: add missing alt attributes, fix Hook usage, and stabilize list keys」,以清晰传达主要改动意图。
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/react-project-health-bde8

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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @chenshuai2144, 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 significantly enhances the project's health and stability by resolving 16 react-doctor identified issues. The changes focus on improving accessibility by adding alt attributes, optimizing React Hook usage and state management patterns, and ensuring proper list rendering with key props, ultimately boosting the project's health score from 79 to 96.

Highlights

  • Improved Accessibility: Added missing alt attributes to <img> tags across various components and demos, enhancing accessibility and resolving react-doctor warnings.
  • Optimized State Management: Refactored state logic in SearchSelect and LightFilter to eliminate derived state in useEffect and leverage useControlledState for more robust and controlled state management.
  • Corrected Hook Usage: Removed the _useEditableDataSource custom hook and its associated helper functions from EditableTable, addressing incorrect Hook usage patterns.
  • Enhanced List Rendering: Introduced key props to dynamically rendered elements in demos/layout/base.tsx, src/form/components/FormItem/Group/index.tsx, and src/form/layouts/LightFilter/index.tsx to improve React's reconciliation process and prevent warnings.
  • Refactored Menu Loading: Updated ProLayout's menu loading mechanism to directly use menuOnLoadingChange and useControlledState, removing a custom setMenuLoading wrapper that could lead to React warnings related to state updates during rendering.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • demos/layout/appList-group-simple.tsx
    • Added alt attribute to img tag
  • demos/layout/base.tsx
    • Added alt attribute to img tag
    • Added key prop to SearchInput component
  • demos/layout/topMode.tsx
    • Added alt attribute to img tag
  • src/field/components/Select/SearchSelect/index.tsx
    • Imported useControlledState
    • Replaced useState with useControlledState for searchValue
    • Removed useEffect for searchValue updates
  • src/form/components/FormItem/Group/index.tsx
    • Added key prop to a hidden div element
  • src/form/layouts/LightFilter/index.tsx
    • Refactored moreValues state initialization to remove derived state in useEffect
    • Added key prop to LightFilterContainer
  • src/form/layouts/LoginForm/index.tsx
    • Added alt attribute to img tag
  • src/form/layouts/LoginFormPage/index.tsx
    • Added alt attribute to img tag
  • src/layout/ProLayout.tsx
    • Updated logo prop examples to include alt attribute
    • Refactored menu loading state management, replacing setMenuLoadingInner with _setMenuLoadingInner and setMenuLoading with direct menuOnLoadingChange calls
    • Removed a custom setMenuLoading useCallback
    • Added alt attribute to img tag within BaseProLayout
  • src/table/components/EditableTable/index.tsx
    • Removed TablePaginationConfig import
    • Removed imports for editableRowByKey and recordKeyToString
    • Removed handleNestedRowInsert, handlePaginationInsert, and _useEditableDataSource functions
  • tests/layout/index.test.tsx
    • Added alt attribute to img tag
Activity
  • No specific activity has been recorded for this pull request yet.
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
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

This pull request improves the project's health by addressing several issues reported by react-doctor. The changes include adding missing alt attributes to images and key attributes to list elements, which are great for accessibility and React best practices.

The refactoring to remove derived state from useEffect and useMemo in LightFilter and ProLayout is a significant improvement for maintainability and correctness.

However, I've found a couple of instances where useControlledState from @rc-component/util seems to be used incorrectly. The arguments appear to be swapped, which could lead to unexpected behavior in controlled components. Please see my detailed comments on these.

A11y 修复:
- 将可点击的 <a> 改为 <button>(demos/tests)
- FormItem/Group: 为可折叠标题添加 role、tabIndex、onKeyDown
- 测试: 为 menuItemRender 的 div 添加键盘事件支持

正确性修复:
- ProLayout: bgLayoutImgList 使用 item.src 作为 key 替代 index

架构优化:
- LightFilter: 将 renderCollapseLabelRender 提取为 collapseLabelNode useMemo

react-doctor: 96 → 99,警告 33 → 3(剩余为组件拆分建议)

Co-authored-by: 陈帅 <[email protected]>
@chenshuai2144 chenshuai2144 marked this pull request as ready for review February 26, 2026 07:04
Copilot AI review requested due to automatic review settings February 26, 2026 07:04
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Feb 26, 2026
@dosubot dosubot bot added ⭕️ bug Something isn't working 🧱 antd labels Feb 26, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the React project health by fixing 16 react-doctor errors, increasing the health score from 79 to 96. The changes focus on accessibility improvements, proper React Hook usage, and eliminating anti-patterns.

Changes:

  • Added missing alt attributes to all <img> tags throughout the codebase for accessibility compliance
  • Enhanced keyboard accessibility by adding role="button", tabIndex={0}, and onKeyDown handlers to clickable div elements
  • Replaced anchor tags with proper button elements where appropriate, using unstyled button styling
  • Fixed React Hook issues by migrating from useState + useEffect pattern to useControlledState hook
  • Eliminated derived state anti-patterns in useEffect hooks
  • Added missing key props to list items with meaningful identifiers
  • Removed unused code (_useEditableDataSource function and related helpers) from EditableTable component

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/layout/index.test.tsx Added accessibility attributes and replaced anchor tags with buttons in test fixtures
tests/layout/snapshots/index.test.tsx.snap Updated snapshots to reflect CSS class changes and structural modifications
src/table/components/EditableTable/index.tsx Removed unused _useEditableDataSource function and related helper functions
src/layout/ProLayout.tsx Fixed derived state issue with menu loading, added alt attributes, improved key props
src/form/layouts/LoginFormPage/index.tsx Added alt attribute to logo image
src/form/layouts/LoginForm/index.tsx Added alt attribute to logo image
src/form/layouts/LightFilter/index.tsx Eliminated derived state by using component key-based remounting, converted function to memoized value
src/form/components/FormItem/Group/index.tsx Added keyboard accessibility handlers and key prop to hidden div
src/field/components/Select/SearchSelect/index.tsx Migrated from useState+useEffect to useControlledState hook
demos/layout/topMode.tsx Added alt attribute, keyboard accessibility, and replaced anchor with button
demos/layout/base.tsx Added alt attribute, keyboard accessibility, key prop, and replaced anchor with button
demos/layout/appList-group-simple.tsx Added alt attribute to image

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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: 3

Caution

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

⚠️ Outside diff range comments (1)
demos/layout/base.tsx (1)

1-508: ⚠️ Potential issue | 🟡 Minor

需要更新快照

Pipeline 失败显示快照不匹配,这是由于 DOM 结构变更(如添加 roletabIndex 属性和替换元素类型)导致的。请运行以下命令更新快照:

pnpm run test -u
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demos/layout/base.tsx` around lines 1 - 508, Tests are failing because the
DOM changed (e.g., added role/tabIndex and element replacements in
menuItemRender/headerTitleRender/MenuCard), so update the Jest snapshots by
running the test update command; run pnpm run test -u from the repo root, review
the updated snapshot files to ensure the new attributes (menuItemRender's
role/tabIndex/keyboard handling and headerTitleRender/MenuCard markup) are
intended, then commit the updated snapshot changes.
🧹 Nitpick comments (2)
src/form/components/FormItem/Group/index.tsx (1)

168-181: 建议添加 aria-labelaria-expanded 以完善无障碍支持。

根据编码规范,具有 role="button" 的元素应包含 aria-label 属性。对于可折叠的组件,aria-expanded 也能帮助屏幕阅读器用户理解当前状态。

此外,按照规范,事件处理函数应使用 "handle" 前缀命名(如 handleTitleClickhandleTitleKeyDown)。

♻️ 建议的改进
+    const handleTitleClick = useCallback(() => {
+      setCollapsed(!collapsed);
+    }, [collapsed, setCollapsed]);
+
+    const handleTitleKeyDown = useCallback(
+      (e: React.KeyboardEvent) => {
+        if (e.key === 'Enter' || e.key === ' ') {
+          e.preventDefault();
+          setCollapsed(!collapsed);
+        }
+      },
+      [collapsed, setCollapsed],
+    );

然后在 JSX 中使用:

             <div
               role="button"
               tabIndex={0}
+              aria-label={typeof title === 'string' ? title : undefined}
+              aria-expanded={collapsible ? !collapsed : undefined}
               className={clsx(`${className}-title`, hashId)}
               style={titleStyle}
-              onClick={() => {
-                setCollapsed(!collapsed);
-              }}
-              onKeyDown={(e) => {
-                if (e.key === 'Enter' || e.key === ' ') {
-                  e.preventDefault();
-                  setCollapsed(!collapsed);
-                }
-              }}
+              onClick={handleTitleClick}
+              onKeyDown={handleTitleKeyDown}
             >

Based on learnings: "Implement accessibility features on elements. For example, a tag should have a tabindex="0", aria-label, on:click, and on:keydown, and similar attributes."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/components/FormItem/Group/index.tsx` around lines 168 - 181, The
clickable title div using role="button" should include accessibility attributes
and clearer handler names: add aria-label (e.g., `${className}-collapse-toggle`)
and aria-expanded={String(!collapsed)} to the div, and extract the inline
handlers into named functions handleTitleClick (calls setCollapsed(!collapsed))
and handleTitleKeyDown (checks e.key === 'Enter' || e.key === ' ' to
preventDefault and toggle via setCollapsed). Update the JSX for the element that
uses className, hashId, titleStyle and setCollapsed/collapsed to use
handleTitleClick and handleTitleKeyDown and ensure the aria attributes are
present.
src/form/layouts/LightFilter/index.tsx (1)

312-312: 使用 JSON.stringify 作为 key 可能存在性能问题

使用 JSON.stringify(values || {}) 作为 key 会导致:

  1. 每次 values 变化时,LightFilterContainer 会完全卸载并重新挂载
  2. JSON.stringify 对于复杂对象的序列化成本较高
  3. 可能导致子组件的内部状态丢失

如果目的是在 values 变化时重置 moreValues,建议考虑以下替代方案:

♻️ 建议使用更轻量的 key 策略

可以考虑使用 values 的长度或特定字段的组合作为 key,而不是完整的 JSON 序列化:

- key={JSON.stringify(values || {})}
+ key={Object.keys(values || {}).join(',')}

或者,如果确实需要在 values 变化时同步 moreValues,可以在 LightFilterContainer 中使用 useEffect:

useEffect(() => {
  setMoreValues({ ...values });
}, [values]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/form/layouts/LightFilter/index.tsx` at line 312, The current
key={JSON.stringify(values || {})} on LightFilterContainer causes full
unmount/remount on any values change and is expensive; replace this strategy by
using a lighter, stable key (e.g., a composite of specific identifying fields or
values length) or remove the key entirely and instead synchronize moreValues
inside LightFilterContainer by watching values and calling setMoreValues({
...values }) in a useEffect; locate the key usage and the LightFilterContainer
component and apply one of these fixes to avoid costly JSON.stringify and
preserve child state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@demos/layout/topMode.tsx`:
- Line 358: Fix the typo in the onClick handler string: replace the malformed
log text "titheaderTitle clicked" with the correct "headerTitle clicked" inside
the onClick callback (the inline arrow function used for the headerTitle click
handler) in topMode.tsx so the console message correctly reads "headerTitle
clicked".

In `@src/layout/ProLayout.tsx`:
- Line 762: The bgLayoutImgList rendering uses item.src as the preferred key
(see key={item.src ?? `bg-layout-${index}`}) which can produce duplicate keys
when multiple items share the same src; update the key to guarantee uniqueness
by combining item.src with a stable unique identifier such as the index or an
item id (e.g., use `${item.src ?? 'bg-layout'}-${index}` or item.id when
available) in the component rendering bgLayoutImgList so each element has a
deterministic, unique key; modify the key expression where key={item.src ??
`bg-layout-${index}`} is used (in the ProLayout component) to the new combined
unique-key format.
- Around line 452-455: The internal menu loading setter (_setMenuLoadingInner)
is never called, so menuLoadingState doesn't update on subsequent requests;
update the code paths that notify loading (the menuOnLoadingChange handler and
any effect watching isLoading used around isLoading and
actionRef.current.reload) to call _setMenuLoadingInner(true/false) when loading
starts/ends and then call menu?.onLoadingChange?.(value). Specifically, inside
the menuOnLoadingChange function call _setMenuLoadingInner(loading) before/after
invoking menu?.onLoadingChange?.(loading), and also ensure the effect or logic
that reacts to isLoading (the code near where isLoading is used around lines
~518) sets _setMenuLoadingInner(isLoading) so SWR revalidation and
actionRef.current.reload scenarios reflect the true loading state.

---

Outside diff comments:
In `@demos/layout/base.tsx`:
- Around line 1-508: Tests are failing because the DOM changed (e.g., added
role/tabIndex and element replacements in
menuItemRender/headerTitleRender/MenuCard), so update the Jest snapshots by
running the test update command; run pnpm run test -u from the repo root, review
the updated snapshot files to ensure the new attributes (menuItemRender's
role/tabIndex/keyboard handling and headerTitleRender/MenuCard markup) are
intended, then commit the updated snapshot changes.

---

Nitpick comments:
In `@src/form/components/FormItem/Group/index.tsx`:
- Around line 168-181: The clickable title div using role="button" should
include accessibility attributes and clearer handler names: add aria-label
(e.g., `${className}-collapse-toggle`) and aria-expanded={String(!collapsed)} to
the div, and extract the inline handlers into named functions handleTitleClick
(calls setCollapsed(!collapsed)) and handleTitleKeyDown (checks e.key ===
'Enter' || e.key === ' ' to preventDefault and toggle via setCollapsed). Update
the JSX for the element that uses className, hashId, titleStyle and
setCollapsed/collapsed to use handleTitleClick and handleTitleKeyDown and ensure
the aria attributes are present.

In `@src/form/layouts/LightFilter/index.tsx`:
- Line 312: The current key={JSON.stringify(values || {})} on
LightFilterContainer causes full unmount/remount on any values change and is
expensive; replace this strategy by using a lighter, stable key (e.g., a
composite of specific identifying fields or values length) or remove the key
entirely and instead synchronize moreValues inside LightFilterContainer by
watching values and calling setMoreValues({ ...values }) in a useEffect; locate
the key usage and the LightFilterContainer component and apply one of these
fixes to avoid costly JSON.stringify and preserve child state.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a07592d and a356081.

⛔ Files ignored due to path filters (1)
  • tests/layout/__snapshots__/index.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (11)
  • demos/layout/appList-group-simple.tsx
  • demos/layout/base.tsx
  • demos/layout/topMode.tsx
  • src/field/components/Select/SearchSelect/index.tsx
  • src/form/components/FormItem/Group/index.tsx
  • src/form/layouts/LightFilter/index.tsx
  • src/form/layouts/LoginForm/index.tsx
  • src/form/layouts/LoginFormPage/index.tsx
  • src/layout/ProLayout.tsx
  • src/table/components/EditableTable/index.tsx
  • tests/layout/index.test.tsx

- topMode: 修正 console.log 拼写 titheaderTitle -> headerTitle
- ProLayout: 使用 isValidating 替代 isLoading,修复 actionRef.reload() 重刷时
  菜单 loading 不更新问题(isLoading 仅在初次请求为 true,revalidate 时需 isValidating)
- tests: menuItemRender 使用 vi.fn() 替代 void 表达式,提供可测试的 click 行为

useControlledState: @rc-component/util 签名为 (defaultValue, controlledValue),
当前用法正确,无需调整

Co-authored-by: 陈帅 <[email protected]>
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/layout/index.test.tsx`:
- Around line 69-76: The onKeyDown handler for the element with role="button"
(where handleMenuItemClick(item.path) is called) does not call
e.preventDefault(), so pressing Space can trigger page scrolling; update the
onKeyDown callback to call e.preventDefault() when the activating keys are
detected (Space and Enter) before invoking handleMenuItemClick. Locate the
onKeyDown attached to the role="button" and add e.preventDefault() for the
branch that handles e.key === 'Enter' or e.key === ' ' (and optionally
'Spacebar'/'Space' variants) so keyboard activation matches mouse click
behavior.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a356081 and f0dbf16.

📒 Files selected for processing (3)
  • demos/layout/topMode.tsx
  • src/layout/ProLayout.tsx
  • tests/layout/index.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/layout/ProLayout.tsx

chenshuai2144 and others added 2 commits February 26, 2026 15:24
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Feb 26, 2026

@chenshuai2144 I've opened a new pull request, #9509, to work on those changes. Once the pull request is ready, I'll request review from you.

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

♻️ Duplicate comments (1)
src/layout/ProLayout.tsx (1)

762-762: ⚠️ Potential issue | 🟡 Minor

key 仍可能冲突(src 重复时不唯一)。

当前优先使用 item.src 作为 key,多个相同 src 时会出现重复 key,影响 React diff 稳定性。

💡 建议修改
-            key={item.src ?? `bg-layout-${index}`}
+            key={`${item.src ?? 'bg-layout'}-${index}`}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layout/ProLayout.tsx` at line 762, The current key expression
(key={item.src ?? `bg-layout-${index}`}) can produce duplicates when multiple
items share the same src; change the key to guarantee uniqueness by
incorporating the loop index or a unique identifier (e.g., use `${item.src ??
'bg-layout'}-${index}` or prefer item.id if available) so the key is always
distinct—update the JSX where key is set for the mapped items (the key prop that
currently references item.src and `bg-layout-${index}`) to a deterministic
unique string.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/layout/ProLayout.tsx`:
- Around line 497-509: The fetcher passed to useSWR is calling
menuOnLoadingChange(true/false) even when no menu.request is provided, causing
spurious loading notifications; update the async fetcher used in the useSWR call
to first check if menu?.request exists and immediately return (or resolve to
undefined) without calling menuOnLoadingChange when it's absent, and only invoke
menuOnLoadingChange(true) / menuOnLoadingChange(false) around the actual
menu.request invocation (e.g., reference the existing useSWR fetcher closure,
menu?.request, menuOnLoadingChange, and route?.children/route?.routes to locate
and change the logic).

---

Duplicate comments:
In `@src/layout/ProLayout.tsx`:
- Line 762: The current key expression (key={item.src ?? `bg-layout-${index}`})
can produce duplicates when multiple items share the same src; change the key to
guarantee uniqueness by incorporating the loop index or a unique identifier
(e.g., use `${item.src ?? 'bg-layout'}-${index}` or prefer item.id if available)
so the key is always distinct—update the JSX where key is set for the mapped
items (the key prop that currently references item.src and `bg-layout-${index}`)
to a deterministic unique string.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0dbf16 and e4e908a.

📒 Files selected for processing (2)
  • src/field/components/Select/SearchSelect/index.tsx
  • src/layout/ProLayout.tsx

Comment on lines +497 to +509
const { data, mutate, isValidating } = useSWR(
[defaultId, menu?.params],
async ([, params]) => {
setMenuLoading(true);
const menuDataItems = await menu?.request?.(
params || {},
route?.children || route?.routes || [],
);
setMenuLoading(false);
return menuDataItems;
menuOnLoadingChange(true);
try {
const menuDataItems = await menu?.request?.(
params || {},
route?.children || route?.routes || [],
);
return menuDataItems;
} finally {
menuOnLoadingChange(false);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/layout/ProLayout.tsx | sed -n '490,520p'

Repository: ant-design/pro-components

Length of output: 1045


🏁 Script executed:

# First, let's find the type definition for menu parameter
head -100 src/layout/ProLayout.tsx | cat -n

# Then search for menuOnLoadingChange and menu?.request usage
rg "menu\?.request|menuOnLoadingChange" src/layout/ProLayout.tsx -A 2 -B 2

Repository: ant-design/pro-components

Length of output: 4702


🏁 Script executed:

# Search for the menu type definition in ProLayoutProps
rg "menu\s*\?*:" src/layout/ProLayout.tsx -A 5 | head -50

# Also check typing.ts for menu-related types
fd typing.ts src/layout/ -x cat -n {}

Repository: ant-design/pro-components

Length of output: 2403


🏁 Script executed:

# Search for menu type definition in ProLayout.tsx or nearby files
rg "menu.*\?.*:\s*" src/layout/ProLayout.tsx -B 2 -A 3 | head -80

# Also search in the same directory for type definitions
fd -e ts -e tsx src/layout/ | xargs rg "interface.*Menu|type.*Menu" | grep -i "request\|onLoading"

Repository: ant-design/pro-components

Length of output: 1004


🏁 Script executed:

# Search for menu type definition in ProLayout.tsx
rg "menu\s*\?" src/layout/ProLayout.tsx -B 2 -A 2 | head -100

# Search for the interface/type that defines menu with request property
rg "request\s*\?.*:|onLoadingChange\s*\?.*:" src/layout/ -r . -A 2 -B 2

Repository: ant-design/pro-components

Length of output: 1765


🏁 Script executed:

# Get the menu type definition from defaultSettings.ts
cat -n src/layout/defaultSettings.ts | grep -A 30 "onLoadingChange"

Repository: ant-design/pro-components

Length of output: 902


当未提供 menu.request 时,应避免触发 loading 回调。

SWR 会在 menu?.params 变化时重新运行,即使 menu?.request 为空也会调用 menuOnLoadingChange(true/false),导致外部监听方收到不必要的"伪 loading"通知。建议在函数开始处进行判空,防止无效的 loading 状态变更。

建议修改
  const { data, mutate, isValidating } = useSWR(
    [defaultId, menu?.params],
    async ([, params]) => {
+     if (!menu?.request) {
+       return undefined;
+     }
      menuOnLoadingChange(true);
      try {
-       const menuDataItems = await menu?.request?.(
+       const menuDataItems = await menu.request(
          params || {},
          route?.children || route?.routes || [],
        );
        return menuDataItems;
      } finally {
        menuOnLoadingChange(false);
      }
    },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layout/ProLayout.tsx` around lines 497 - 509, The fetcher passed to
useSWR is calling menuOnLoadingChange(true/false) even when no menu.request is
provided, causing spurious loading notifications; update the async fetcher used
in the useSWR call to first check if menu?.request exists and immediately return
(or resolve to undefined) without calling menuOnLoadingChange when it's absent,
and only invoke menuOnLoadingChange(true) / menuOnLoadingChange(false) around
the actual menu.request invocation (e.g., reference the existing useSWR fetcher
closure, menu?.request, menuOnLoadingChange, and route?.children/route?.routes
to locate and change the logic).

@rc-component/util 签名为 (defaultStateValue, value),非 options 对象形式,
修正 SearchSelect 和 ProLayout 的调用以避免 TS2345 声明生成失败

Co-authored-by: 陈帅 <[email protected]>
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.

♻️ Duplicate comments (2)
src/layout/ProLayout.tsx (2)

497-509: ⚠️ Potential issue | 🟡 Minor

menu?.request 未提供时,应避免触发 loading 回调。

即使 menu?.requestundefined,SWR fetcher 仍会执行并调用 menuOnLoadingChange(true/false),导致不必要的 loading 状态变更。建议在调用前判空。

建议修改
  const { data, mutate, isValidating } = useSWR(
    [defaultId, menu?.params],
    async ([, params]) => {
+     if (!menu?.request) {
+       return undefined;
+     }
      menuOnLoadingChange(true);
      try {
-       const menuDataItems = await menu?.request?.(
+       const menuDataItems = await menu.request(
          params || {},
          route?.children || route?.routes || [],
        );
        return menuDataItems;
      } finally {
        menuOnLoadingChange(false);
      }
    },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layout/ProLayout.tsx` around lines 497 - 509, The SWR fetcher currently
calls menuOnLoadingChange(true/false) even when menu?.request is undefined;
update the fetcher passed to useSWR (the async ([, params]) => { ... } function)
to first check if menu?.request exists and if not return early (no
menuOnLoadingChange calls), and only call menuOnLoadingChange and await
menu.request(params, route?.children || route?.routes || []) when menu?.request
is present; reference the fetcher function, menu?.request, and
menuOnLoadingChange to locate and fix the logic.

762-762: ⚠️ Potential issue | 🟡 Minor

bgLayoutImgList 的 key 在多个 src 相同时会产生冲突。

当前 key={item.src ?? \bg-layout-${index}`}仅在src为空时使用index,多项拥有相同 src` 时会产生重复的 key。

建议修改
- key={item.src ?? `bg-layout-${index}`}
+ key={`${item.src ?? 'bg-layout'}-${index}`}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layout/ProLayout.tsx` at line 762, The key for items in bgLayoutImgList
(currently rendered with key={item.src ?? `bg-layout-${index}`}) can collide
when multiple items share the same src; update the key generation in the
ProLayout.tsx render to ensure uniqueness by incorporating the index (or another
unique identifier) together with the src (e.g., use a template like `${item.src
?? 'bg-layout'}-${index}`) so each element has a stable, unique key even when
src values repeat.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/layout/ProLayout.tsx`:
- Around line 497-509: The SWR fetcher currently calls
menuOnLoadingChange(true/false) even when menu?.request is undefined; update the
fetcher passed to useSWR (the async ([, params]) => { ... } function) to first
check if menu?.request exists and if not return early (no menuOnLoadingChange
calls), and only call menuOnLoadingChange and await menu.request(params,
route?.children || route?.routes || []) when menu?.request is present; reference
the fetcher function, menu?.request, and menuOnLoadingChange to locate and fix
the logic.
- Line 762: The key for items in bgLayoutImgList (currently rendered with
key={item.src ?? `bg-layout-${index}`}) can collide when multiple items share
the same src; update the key generation in the ProLayout.tsx render to ensure
uniqueness by incorporating the index (or another unique identifier) together
with the src (e.g., use a template like `${item.src ?? 'bg-layout'}-${index}`)
so each element has a stable, unique key even when src values repeat.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 223007b and e84f6b6.

📒 Files selected for processing (2)
  • src/field/components/Select/SearchSelect/index.tsx
  • src/layout/ProLayout.tsx

@chenshuai2144 chenshuai2144 merged commit 003548e into master Feb 26, 2026
9 of 11 checks passed
@chenshuai2144 chenshuai2144 deleted the cursor/react-project-health-bde8 branch February 26, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🧱 antd ⭕️ bug Something isn't working layout list size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants