Skip to content

Conversation

EmilyyyLiu
Copy link

@EmilyyyLiu EmilyyyLiu commented Sep 11, 2025

关联issue:ant-design/ant-design#54854
替换 useMergedState 为 useControlledState

Summary by CodeRabbit

  • Refactor
    • 优化 Collapse 的状态管理为更健壮的受控/非受控模式,统一单/多激活键的处理;简化点击逻辑,只有在实际激活键变化时才触发 onChange,减少冗余回调并提升交互一致性。
  • Chores
    • 升级依赖 @rc-component/util 至 ^1.3.0,以获得更稳定的工具支持。

Copy link

vercel bot commented Sep 11, 2025

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

Project Deployment Preview Comments Updated (UTC)
collapse Ready Ready Preview Comment Sep 11, 2025 8:04am

Copy link

coderabbitai bot commented Sep 11, 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

对 Collapse 组件的内部状态管理进行了重构:由 useMergedState 切换为 useControlledState 与 useEvent 的受控/非受控模式;统一通过 getActiveKeysArray 派生 activeKey,并使用 triggerActiveKey 进行状态更新与 onChange 调用。并将 @rc-component/util 依赖从 ^1.0.1 升级到 ^1.3.0。

Changes

Cohort / File(s) Summary
Dependency bump
package.json
将依赖 @rc-component/util^1.0.1 升级到 ^1.3.0
Collapse state refactor
src/Collapse.tsx
useControlledState/useEvent 替换 useMergedState;通过 getActiveKeysArray 统一派生 activeKey(返回类型 React.Key[]);新增 triggerActiveKey 统一更新内部状态并在实际变化时触发 onChange;重写 onItemClick 以基于派生的 activeKey 计算下一状态;调整导入路径与部分类型标注,公共 API 无变化。

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as 用户
  participant C as Collapse
  participant S as useControlledState
  participant E as useEvent (triggerActiveKey)
  participant P as 父组件 onChange

  U->>C: 点击 Panel Header
  C->>C: onItemClick 计算 nextKeys(手风琴/多选)
  C->>E: 调用 triggerActiveKey(nextKeys)
  E->>C: 派生 currentKeys = getActiveKeysArray(internal)
  alt nextKeys 与 currentKeys 不同
    E->>S: setInternal(nextKeys)
    E-->>P: 触发 onChange(nextKeys)
  else 无变化
    E-->>C: 不做状态更新/不触发 onChange
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • zombieJ

Poem

代码篱下风轻拂,键阵排成新队伍。
兔子点头“咔嗒”响,受控自如不含糊。
一键一阵皆有序,onChange 只在真起伏。
依赖攀升又一阶,轻跃版本喜洋洋。 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b08776 and 517d597.

📒 Files selected for processing (1)
  • src/Collapse.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Collapse.tsx

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 标题“refactor: Upgrade utils and replace useMergedState” 简洁且直接反映了 PR 的核心改动,即升级工具相关依赖并将 useMergedState 替换为新的受控状态 Hook(useControlledState / useEvent),这与提供的变更摘要和 PR 目标一致;标题没有包含文件列表、表情或模糊术语,可让同事快速理解主要目的并便于历史检索;长度适中,信息明确。
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • 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

@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.

Summary of Changes

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

此 PR 主要进行了一项重构,旨在更新项目所依赖的工具库版本,并替换组件内部的状态管理 Hook。通过升级 @rc-component/util 并迁移到 useControlledState,提高了组件对受控和非受控状态处理的灵活性和一致性,同时优化了事件触发机制。

Highlights

  • 依赖升级: 将 package.json 中的 @rc-component/util 版本从 ^1.0.1 升级到 ^1.3.0
  • 替换状态管理 Hook: 在 src/Collapse.tsx 中,将 useMergedState 替换为 useControlledStateuseEvent
  • 重构 activeKey 逻辑: 调整 Collapse 组件中 activeKey 的状态管理逻辑,以适应 useControlledState 的使用,并优化 onItemClick 的触发方式。
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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

socket-security bot commented Sep 11, 2025

Copy link

@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 主要是将 @rc-component/util 依赖从 ^1.0.1 升级到 ^1.3.0,并用 useControlledState 替换了已废弃的 useMergedState。整体重构方向是正确的,但有两处可以改进:一处是 triggerActiveKey 中对数组的比较逻辑有误,可能导致不必要的 onChange 事件触发;另一处是 onItemClick 的逻辑虽然正确,但可读性不佳,建议重构以提高代码的可维护性。

src/Collapse.tsx Outdated
Comment on lines 49 to 51
if (next !== activeKey) {
onChange?.(next);
}

Choose a reason for hiding this comment

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

high

triggerActiveKey 函数中,使用 next !== activeKey 来判断数组是否发生变化是不正确的。因为 nextactiveKey 总是不同的数组实例,即使它们的内容完全相同,这个条件也始终为 true。这会导致 onChange 回调在每次点击时都会被不必要地触发,可能引起父组件的额外渲染。之前的 useMergedState 内部使用了浅比较来避免此问题,建议此处也实现一个浅比较逻辑。

    if (
      next.length !== activeKey.length ||
      next.some((key, index) => key !== activeKey[index])
    ) {
      onChange?.(next);
    }

Comment on lines +54 to +65
const onItemClick = (key: React.Key) => {
let keys = [...activeKey, key];
if (accordion) {
keys = activeKey[0] === key ? [] : [key];
}
const index = activeKey.indexOf(key);
const isActive = index > -1;
if (isActive) {
keys = activeKey.filter((item) => item !== key);
}
triggerActiveKey(keys);
};

Choose a reason for hiding this comment

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

medium

当前的 onItemClick 函数逻辑虽然是正确的,但代码结构有些迂回,可读性不强。代码首先假定添加 key,然后根据 accordion 模式和 isActive 状态覆盖这个值。为了提高代码的可读性和可维护性,建议重构此函数,使用更明确的 if/else 结构来处理不同情况。

  const onItemClick = (key: React.Key) => {
    let newKeys: React.Key[];

    if (accordion) {
      newKeys = activeKey[0] === key ? [] : [key];
    } else {
      const index = activeKey.indexOf(key);
      const isActive = index > -1;
      if (isActive) {
        newKeys = activeKey.filter((item) => item !== key);
      } else {
        newKeys = [...activeKey, key];
      }
    }

    triggerActiveKey(newKeys);
  };

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

🧹 Nitpick comments (2)
src/Collapse.tsx (2)

10-18: 建议优化类型安全性

getActiveKeysArray 函数实现正确,但可以通过更严格的类型检查来提高代码质量。

 function getActiveKeysArray(activeKey: React.Key | React.Key[]): React.Key[] {
   let currentActiveKey = activeKey;
   if (!Array.isArray(currentActiveKey)) {
-    const activeKeyType = typeof currentActiveKey;
-    currentActiveKey =
-      activeKeyType === 'number' || activeKeyType === 'string' ? [currentActiveKey] : [];
+    currentActiveKey = 
+      currentActiveKey !== undefined && currentActiveKey !== null ? [currentActiveKey] : [];
   }
   return currentActiveKey.map((key) => String(key));
 }

这种方式可以更好地处理 nullundefined 值,同时简化逻辑。


54-65: 建议简化 onItemClick 逻辑

当前实现功能正确,但可以通过提前返回来简化逻辑流程。

 const onItemClick = (key: React.Key) => {
-  let keys = [...activeKey, key];
   if (accordion) {
-    keys = activeKey[0] === key ? [] : [key];
+    const keys = activeKey[0] === key ? [] : [key];
+    triggerActiveKey(keys);
+    return;
   }
+  
   const index = activeKey.indexOf(key);
   const isActive = index > -1;
-  if (isActive) {
-    keys = activeKey.filter((item) => item !== key);
-  }
+  const keys = isActive 
+    ? activeKey.filter((item) => item !== key)
+    : [...activeKey, key];
   triggerActiveKey(keys);
 };

这种方式使手风琴模式和多选模式的逻辑更加清晰分离。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc63f6b and 6b08776.

📒 Files selected for processing (2)
  • package.json (1 hunks)
  • src/Collapse.tsx (2 hunks)
🔇 Additional comments (3)
package.json (1)

50-50: 依赖版本升级看起来不错!

@rc-component/util^1.0.1 升级到 ^1.3.0 以支持新的 useControlledStateuseEvent hooks 是合理的。这个版本升级幅度适中,应该不会引入破坏性变更。

src/Collapse.tsx (2)

2-2: 成功迁移到新的状态管理模式

useMergedState 迁移到 useControlledStateuseEvent 的组合是一个很好的重构,使代码更加清晰和符合现代 React 模式。


41-45: 状态管理实现正确

使用 useControlledState 处理受控/非受控模式,并通过 getActiveKeysArray 派生 activeKey 的实现很清晰。这种模式能够正确处理各种输入类型。

Copy link

codecov bot commented Sep 11, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.20%. Comparing base (bc63f6b) to head (517d597).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #400      +/-   ##
==========================================
+ Coverage   99.15%   99.20%   +0.04%     
==========================================
  Files           5        5              
  Lines         118      125       +7     
  Branches       43       46       +3     
==========================================
+ Hits          117      124       +7     
  Misses          1        1              

☔ 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.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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.

1 participant