Skip to content

feat(switch): 异步切换支持受控loading态 #3122

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

Merged
merged 4 commits into from
Mar 28, 2025

Conversation

irisSong
Copy link
Collaborator

@irisSong irisSong commented Mar 25, 2025

🤔 这个变动的性质是?

  • 新特性提交
  • 日常 bug 修复
  • 站点、文档改进
  • 演示代码改进
  • 组件样式/交互改进
  • TypeScript 定义更新
  • 包体积优化
  • 性能优化
  • 功能增强
  • 国际化改进
  • 重构
  • 代码风格优化
  • 测试用例
  • 分支合并
  • 其他改动(是关于什么的改动?)

🔗 相关 Issue

💡 需求背景和解决方案

☑️ 请求合并前的自查清单

⚠️ 请自检并全部勾选全部选项⚠️

  • 文档已补充或无须补充
  • 代码演示已提供或无须提供
  • TypeScript 定义已补充或无须补充
  • fork仓库代码是否为最新避免文件冲突
  • Files changed 没有 package.json lock 等无关文件

Summary by CodeRabbit

  • 新功能
    • 增加了异步操作和延迟模拟,保证状态更新顺序清晰,并在切换时显示加载动画,改善了用户体验。
    • 新增 loadingIcon 属性,允许用户指定加载状态图标。
  • 重构
    • 简化了事件处理函数,移除了冗余参数,并对接口类型进行了调整,提升了整体代码的一致性和清晰度。
  • 样式
    • 优化了开关图标的样式,增强了视觉效果。

Copy link

coderabbitai bot commented Mar 25, 2025

Walkthrough

该 PR 修改了多个 Switch 组件及相关 demo 的事件处理、状态管理和样式。主要变化包括对 onChangeAsync 与 onChange 函数签名的简化(移除事件参数)、在 Demo2 中引入异步模拟请求逻辑,以及在 Switch 组件中添加新的状态变量 changing 和相应的副作用(useEffect)来控制加载状态。同时,还更新了相关的类型定义,移除泛型事件参数,从而使接口更加简洁。

Changes

File(s) Change Summary
src/packages/switch/demos/h5/demo2.tsx
src/packages/switch/demos/taro/demo2.tsx
更新 onChangeAsync 函数签名,移除事件参数;h5 版本新增异步处理,调用 mockRequest 模拟 2 秒延迟;Switch 组件 onChange 回调只传递 value 参数。
src/packages/switch/demos/taro/demo6.tsx 修改 onChange 函数签名,移除事件参数,简化回调逻辑。
src/packages/switch/switch.taro.tsx
src/packages/switch/switch.tsx
新增状态变量 changing,并通过 useEffect 重置状态;调整 onClick 函数,不再接收事件参数,在加载状态下显示 Loading1 组件。
src/packages/switch/switch.scss 新增 .nut-icon 样式类,为图标设置尺寸和颜色。
src/types/spec/switch/base.ts
src/types/spec/switch/h5.ts
src/types/spec/switch/taro.ts
更新接口定义,移除泛型事件参数;onChange 方法签名修改为仅接收 boolean 类型参数,简化事件处理。
src/packages/switch/doc.en-US.md
src/packages/switch/doc.md
src/packages/switch/doc.taro.md
src/packages/switch/doc.zh-TW.md
在 Switch 组件文档中新增 loadingIcon 属性,描述为“受控加载状态图标”,类型为 ReactNode,默认值为 。
src/sites/sites-react/doc/docs/react/migrate-from-v2.md
src/sites/sites-react/doc/docs/taro/migrate-from-v2.md
更新 Switch 组件文档,新增 loadingIcon 属性,并将 activeText 和 inactiveText 的类型更新为 ReactNode。
src/packages/switch/__test__/switch.spec.tsx 新增 loadingIcon 测试用例,更新 disabled 测试用例为异步模式,检查按钮元素并模拟点击事件。

Sequence Diagram(s)

sequenceDiagram
    participant U as 用户
    participant D as Demo2组件
    participant F as onChangeAsync
    participant M as mockRequest
    U->>D: 切换开关
    D->>F: 调用 onChangeAsync(value)
    F->>M: await mockRequest()
    M-->>F: 返回延迟结果
    F->>D: 更新状态 (checkedAsync)
Loading
sequenceDiagram
    participant U as 用户
    participant S as Switch组件
    participant C as onClick()
    participant E as useEffect
    U->>S: 点击开关
    S->>C: 调用 onClick()
    C->>S: 检查 disabled/changing 状态
    S->>S: 设置 changing 为 true(若可操作)
    S->>P: 调用 props.onChange(!value)
    P-->>S: 更新 value 状态
    S->>E: useEffect 检测到 value 改变
    E->>S: 重置 changing 为 false,结束加载状态
Loading

Possibly related PRs

Suggested reviewers

  • oasis-cloud
  • Alex-huxiyang

Poem

我是一只快乐的小兔子,
在代码花园中轻巧蹦跶,
异步请求如风拂面,
状态重置闪耀光华,
变更已至,代码添彩! 🥕😄

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added action:review This PR needs more reviews (less than 2 approvals) 3.x Target branch 3.x labels Mar 25, 2025
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 (1)
src/types/spec/switch/base.ts (1)

10-10:

❓ Verification inconclusive

简化了 onChange 回调函数签名

onChange 方法的签名从 (val: boolean, event: EVENT) => void 变更为 (val: boolean) => void,移除了事件参数。这一变更使接口更加简洁,更符合纯函数的设计理念,并与异步加载状态管理的实现目标相符。

需要注意,此更改可能会影响已经在使用事件参数的现有代码,请确保相应地更新所有调用点。


🏁 Script executed:

#!/bin/bash
# 检查项目中是否有代码依赖 onChange 的事件参数
echo "查找可能受影响的 Switch 组件 onChange 使用点..."
rg "onChange\s*=\s*\{.*\}" --type tsx | grep -E "switch|Switch"
echo "检查 demo 文件中的使用情况..."
rg "onChange.*\(.*, .*\)" --type tsx --glob "**demo*.tsx" | grep -E "switch|Switch"

Length of output: 335


请手动确认 TSX 文件中 Switch 组件 onChange 的调用处

目前变更将 onChange 签名从 (val: boolean, event: EVENT) => void 简化为 (val: boolean) => void,这符合简洁、纯函数化设计的初衷,但有可能影响依赖事件参数的调用场景。初步使用带有 --type tsx 参数的自动搜索因“未识别文件类型”而无法提供有效结果,建议手动核查 TSX 文件中是否存在调用 onChange 时传递两个参数的情况,特别是在 Switch 组件和 demo 文件内。如果确实有调用依赖事件参数的情况,请及时更新相应的调用点。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 384bca0 and d42520d.

📒 Files selected for processing (9)
  • src/packages/switch/demos/h5/demo2.tsx (1 hunks)
  • src/packages/switch/demos/taro/demo2.tsx (2 hunks)
  • src/packages/switch/demos/taro/demo6.tsx (1 hunks)
  • src/packages/switch/switch.scss (1 hunks)
  • src/packages/switch/switch.taro.tsx (4 hunks)
  • src/packages/switch/switch.tsx (4 hunks)
  • src/types/spec/switch/base.ts (1 hunks)
  • src/types/spec/switch/h5.ts (1 hunks)
  • src/types/spec/switch/taro.ts (1 hunks)
🧰 Additional context used
🧬 Code Definitions (4)
src/types/spec/switch/h5.ts (1)
src/types/spec/switch/base.ts (1)
  • BaseSwitch (4-11)
src/types/spec/switch/taro.ts (1)
src/types/spec/switch/base.ts (1)
  • BaseSwitch (4-11)
src/packages/switch/demos/taro/demo6.tsx (2)
src/packages/switch/switch.taro.tsx (1)
  • Switch (17-108)
src/packages/switch/switch.tsx (1)
  • Switch (15-106)
src/packages/switch/demos/h5/demo2.tsx (2)
src/packages/switch/switch.taro.tsx (1)
  • Switch (17-108)
src/packages/switch/switch.tsx (1)
  • Switch (15-106)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (17)
src/types/spec/switch/h5.ts (1)

3-3: 类型定义简化,移除了泛型事件参数

BaseSwitch接口扩展中移除了<React.MouseEvent>泛型参数,使接口定义更简洁。这与BaseSwitch基础接口的更改保持一致,现在onChange方法只接收一个布尔值参数而不是事件对象。

src/packages/switch/switch.scss (1)

43-47: 为加载图标添加样式支持

添加了.nut-icon类样式,定义了图标的宽高和颜色,为Switch组件中的加载图标提供了样式支持。尺寸设置为开关高度的一半减去两倍边框宽度,确保图标在开关按钮中居中显示。

src/types/spec/switch/taro.ts (1)

3-3: 类型定义简化,移除了联合事件类型

BaseSwitch接口扩展中移除了UnionEvent类型参数,与其他组件类型定义的简化保持一致。这一更改简化了事件处理,现在onChange方法只关注布尔值状态而非事件对象。

src/packages/switch/demos/taro/demo2.tsx (1)

9-9: 简化函数签名,移除事件参数

onChangeAsync函数中移除了event参数,只保留了value参数,使函数签名更简洁。这与类型定义的更改保持一致。

src/packages/switch/switch.taro.tsx (4)

1-1: 导入必要的依赖

引入了useStateuseEffectLoading1组件,为实现异步加载状态的功能做好准备。

Also applies to: 3-3, 5-5


41-45: 添加异步加载状态管理

添加了changing状态以及对应的副作用以处理异步状态变化。当value更新时,重置changing状态,确保组件在状态变更后不再显示加载中。


59-64: 改进点击事件处理逻辑

优化了点击事件处理函数,移除了事件参数,增加了对changing状态的检查,防止在异步操作进行时重复触发。在调用onChange前将changing设置为true,为用户提供视觉反馈。


68-68: 实现加载状态的视觉反馈

在组件渲染逻辑中加入了changing状态的判断,当处于changing状态时显示Loading1组件,提供良好的用户体验。

Also applies to: 83-90

src/packages/switch/demos/taro/demo6.tsx (1)

7-10: 简化事件处理函数签名

移除了onChange函数中不必要的事件参数,使API更加简洁。相应地更新了Switch组件的调用方式,仅传递值参数。这种变更与组件的核心实现保持一致性。

Also applies to: 14-14

src/packages/switch/switch.tsx (4)

1-1: 导入必要的依赖

引入了useStateuseEffectLoading1组件,为实现异步加载状态的功能做好准备。

Also applies to: 3-3


39-43: 添加异步加载状态管理

添加了changing状态以及对应的副作用以处理异步状态变化。当value更新时,重置changing状态,确保组件在状态变更后不再显示加载中。


57-62: 改进点击事件处理逻辑

优化了点击事件处理函数,移除了事件参数,增加了对changing状态的检查,防止在异步操作进行时重复触发。在调用onChange前将changing设置为true,为用户提供视觉反馈。


66-66: 实现加载状态的视觉反馈

在组件渲染逻辑中加入了changing状态的判断,当处于changing状态时显示Loading1组件,提供良好的用户体验。此更改确保了Web版本与Taro版本的行为一致性。

Also applies to: 81-89

src/packages/switch/demos/h5/demo2.tsx (3)

7-13: 添加模拟异步请求函数

创建了mockRequest函数来模拟网络请求,使用Promise封装延时操作,为演示异步加载功能提供了良好示例。


15-19: 优化异步处理逻辑

将原有的回调式异步处理改为async/await模式,代码更加清晰易读。使用mockRequest模拟网络请求,充分演示了Switch组件的异步加载功能。


24-24: 更新事件处理方式

更新了Switch组件的事件处理方式,仅传递值参数,与组件新的API设计保持一致。

src/types/spec/switch/base.ts (1)

4-4:

✅ Verification successful

移除了泛型参数,简化了接口设计

接口定义从 BaseSwitch<EVENT = any> 变更为 BaseSwitch,移除了泛型参数 EVENT,使接口定义更加简洁。这种变更有助于简化组件的使用,并与异步加载的特性需求保持一致。


🏁 Script executed:

#!/bin/bash
# 检查是否有现有代码依赖此泛型参数
echo "检查项目中对 Switch 泛型参数的使用情况..."
rg "BaseSwitch\s*<" --type ts
echo "检查对 Switch 组件的实现以确认更改影响..."
rg "onChange.*\(.*, .*\)" --type ts | grep -E "switch|Switch"

Length of output: 412


变更已验证:接口简化改动无问题

  • src/types/spec/switch/base.ts 中,接口已从 BaseSwitch<EVENT = any> 改为 BaseSwitch,去除了泛型参数,设计更简洁。
  • 使用 rg "BaseSwitch\s*<" 搜索后的结果表明项目中未发现对泛型参数的依赖。
  • 搜索结果也显示 Switch 组件的 onChange 回调实现未受影响。

@@ -18,7 +18,7 @@ const Demo2 = () => {
<Cell>
<Switch
checked={checkedAsync}
onChange={(value, event) => onChangeAsync(value, event)}
onChange={(value) => onChangeAsync(value)}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

更新事件处理器,匹配新的函数签名

更新了onChange属性的回调函数,现在只传递value参数给onChangeAsync函数,符合新的函数签名。

在异步操作期间(2秒延迟),应添加加载状态指示器以提升用户体验。建议在Switch组件中添加一个loading属性,并在状态更新前将其设置为true:

+  const [loading, setLoading] = useState(false)

  const onChangeAsync = (value: boolean) => {
    setValue(value)
    setShowToast(true)
+   setLoading(true)
    setTimeout(() => {
      setCheckedAsync(value)
+     setLoading(false)
    }, 2000)
  }

  return (
    <>
      <Cell>
        <Switch
          checked={checkedAsync}
+         loading={loading}
          onChange={(value) => onChangeAsync(value)}
        />
      </Cell>
📝 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
onChange={(value) => onChangeAsync(value)}
import React, { useState } from 'react';
const Demo2 = () => {
const [value, setValue] = useState(false);
const [checkedAsync, setCheckedAsync] = useState(false);
const [showToast, setShowToast] = useState(false);
const [loading, setLoading] = useState(false);
const onChangeAsync = (value: boolean) => {
setValue(value);
setShowToast(true);
setLoading(true);
setTimeout(() => {
setCheckedAsync(value);
setLoading(false);
}, 2000);
};
return (
<>
<Cell>
<Switch
checked={checkedAsync}
loading={loading}
onChange={(value) => onChangeAsync(value)}
/>
</Cell>
</>
);
};
export default Demo2;

Copy link

codecov bot commented Mar 25, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 86.97%. Comparing base (9a903a0) to head (a5b0f57).
Report is 12 commits behind head on feat_v3.x.

Additional details and impacted files
@@              Coverage Diff              @@
##           feat_v3.x    #3122      +/-   ##
=============================================
+ Coverage      86.95%   86.97%   +0.01%     
=============================================
  Files            280      280              
  Lines          18456    18484      +28     
  Branches        2786     2792       +6     
=============================================
+ Hits           16049    16077      +28     
  Misses          2402     2402              
  Partials           5        5              

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

@irisSong irisSong changed the title feat(switch): 异步加载展示loading feat(switch): 异步加载支持受控loading态 Mar 25, 2025
@irisSong irisSong changed the title feat(switch): 异步加载支持受控loading态 feat(switch): 异步切换支持受控loading态 Mar 25, 2025
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: 2

🧹 Nitpick comments (1)
src/packages/switch/switch.tsx (1)

83-91: 实现加载状态的条件渲染

这段代码实现了在 changing 状态下显示加载图标的逻辑。使用了条件渲染:

  • changingtrueloadingIcon 存在时,显示加载图标
  • 否则,在非激活状态且没有设置 activeText 时显示关闭线条

建议添加单元测试确保此渲染逻辑在各种状态组合下能正常工作。

如果将来需要支持更多状态,可以考虑提取一个独立的渲染函数来处理这部分逻辑,提高代码可维护性:

- {changing && loadingIcon ? (
-   <>{loadingIcon}</>
- ) : (
-   <>
-     {!value && !activeText && (
-       <div className={`${classPrefix}-close-line`} />
-     )}
-   </>
- )}
+ {renderSwitchContent()}

并在组件中添加:

const renderSwitchContent = () => {
  if (changing && loadingIcon) {
    return <>{loadingIcon}</>;
  }
  
  return (
    <>
      {!value && !activeText && (
        <div className={`${classPrefix}-close-line`} />
      )}
    </>
  );
};
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 84-84: src/packages/switch/switch.tsx#L84
Added line #L84 was not covered by tests

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84cf723 and 6f4a65e.

📒 Files selected for processing (9)
  • src/packages/switch/doc.en-US.md (1 hunks)
  • src/packages/switch/doc.md (1 hunks)
  • src/packages/switch/doc.taro.md (1 hunks)
  • src/packages/switch/doc.zh-TW.md (1 hunks)
  • src/packages/switch/switch.taro.tsx (6 hunks)
  • src/packages/switch/switch.tsx (6 hunks)
  • src/sites/sites-react/doc/docs/react/migrate-from-v2.md (1 hunks)
  • src/sites/sites-react/doc/docs/taro/migrate-from-v2.md (1 hunks)
  • src/types/spec/switch/base.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/types/spec/switch/base.ts
  • src/packages/switch/switch.taro.tsx
🧰 Additional context used
🪛 GitHub Check: codecov/patch
src/packages/switch/switch.tsx

[warning] 60-64: src/packages/switch/switch.tsx#L60-L64
Added lines #L60 - L64 were not covered by tests


[warning] 84-84: src/packages/switch/switch.tsx#L84
Added line #L84 was not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (11)
src/packages/switch/doc.taro.md (1)

80-80: 新增 loadingIcon 属性说明完善
文档中已正确新增 loadingIcon 属性,清晰地说明了其类型为 ReactNode、默认值为 <Loading1 />,符合组件受控 loading 态的设计要求。建议确认文档中的默认组件与实际 demo 使用一致。

src/packages/switch/doc.md (1)

80-80: 文档 Props 更新准确
在 Props 表中新增的 loadingIcon 属性说明明确,标注为“受控 loading 态图标”,同时提供了默认值 <Loading1 />,描述与预期一致。

src/packages/switch/doc.zh-TW.md (1)

80-80: 屬性說明更新正確
文檔中新增的 loadingIcon 屬性在描述、類型及默認值方面均更新正確,且與其他語言版本保持一致。

src/packages/switch/doc.en-US.md (1)

80-80: 英文文档中的属性描述清晰
在英文文档中,loadingIcon 属性已被正确介绍,标注为“Controlled loading state icon”,类型为 ReactNode,默认值为 <Loading1 />。虽然文档语言为英文,但说明内容无歧义,建议保持与其他版本一致。

src/sites/sites-react/doc/docs/taro/migrate-from-v2.md (1)

231-232: 升级文档中 loadingIcon 属性说明完善
在迁移指南中,新增了 loadingIcon 属性的介绍,有助于开发者理解新版 Switch 组件 API 的变更。描述与其它文档版本保持一致,利于平滑过渡。

src/sites/sites-react/doc/docs/react/migrate-from-v2.md (1)

228-228: 文档更新与组件变更一致

文档中新增的 loadingIcon 属性描述与实际代码实现相符,清晰地表明了这是一个用于受控加载态图标的新属性。

src/packages/switch/switch.tsx (5)

1-3: 导入必要的钩子和图标

导入了 useEffect 钩子用于处理异步状态变化,以及导入了 Loading1 图标组件用作默认的加载状态图标。


14-14: 设置合理的默认加载图标

loadingIcon 属性设置了默认值,使用 Loading1 组件作为默认加载图标,符合用户预期。


23-23: 从 props 中解构新属性

从 props 中解构出 loadingIcon 属性,与其他属性保持一致的处理方式。


68-68: 移除 onClick 处理程序中的事件参数

这一变更与上面 onClick 函数定义的更改保持一致,移除了事件参数的传递。


59-66:

❓ Verification inconclusive

优化点击事件处理逻辑

更新后的 onClick 函数移除了事件参数,简化了接口,并添加了两项重要功能:

  1. 当组件处于 disabledchanging 状态时阻止点击
  2. 在触发 onChange 前设置 changing 状态为 true

这种实现方式能够有效防止用户在异步操作进行时重复点击,提升了用户体验。

但这部分代码没有测试覆盖,建议添加测试用例确保这一重要功能正常工作。


🏁 Script executed:

#!/bin/bash
# 查找现有的 demo 文件,检查是否有演示异步加载状态的示例
echo "查找 Switch 组件的 demo 文件..."
fd "demo.*\.tsx" --path-regexp "packages/switch/demos"

Length of output: 336


注意:请补充单元测试验证异步状态下的防重复点击逻辑

你在 src/packages/switch/switch.tsx(第 59-66 行)中更新的 onClick 处理逻辑已成功移除事件参数、简化接口,并在以下两处做了关键处理:

  • 在组件处于 disabledchanging 状态时提前阻止后续点击;
  • 触发 props.onChange 前先设置 changing 状态为 true,从而防止复点击的副作用。

目前尚未看到相关的单元测试或 demo 文件来覆盖这个异步操作防重复点击的逻辑。请手动核实或添加对应测试用例以确保这一重要功能在异步场景下始终正常工作。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 60-64: src/packages/switch/switch.tsx#L60-L64
Added lines #L60 - L64 were not covered by tests

Comment on lines +60 to 66
if (disabled || changing) return
if (props.onChange) {
setChanging(true)
props.onChange(!value)
}
setValue(!value)
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

需要添加测试覆盖新增功能

静态分析工具显示这些关键的新增代码行没有测试覆盖,特别是:

  1. 异步加载状态的处理逻辑
  2. 加载图标的渲染

建议增加测试用例确保这些功能在各种条件下正常工作,例如:

  • 测试点击后的 changing 状态变化
  • 测试 value 更新后 changing 状态的重置
  • 测试加载图标的正确渲染
  • 测试在 changing 状态下点击不触发 onChange

这些测试对确保组件的稳定性和可靠性非常重要。

Also applies to: 84-84


🏁 Script executed:

#!/bin/bash
# 查找与 Switch 组件相关的测试文件和测试覆盖情况
echo "检查 Switch 组件的测试文件..."
fd "switch.*test" --type f

echo "检查测试中是否已经测试了异步处理逻辑..."
if fd "switch.*test" --type f | xargs rg -l "changing|loading|async"; then
  echo "找到了可能包含异步处理逻辑测试的文件"
else
  echo "未找到包含异步处理逻辑测试的文件"
fi

Length of output: 13008


请完善测试覆盖异步状态和加载图标功能

目前静态分析工具提示,新增的代码逻辑缺少相应的测试验证,建议对以下情况补充测试用例:

  • 点击事件后 changing 状态的变化:验证点击后是否正确设置 changing 状态,以及在 value 更新后该状态是否能重置。
  • 加载图标的渲染:确保在异步加载状态下加载图标能够正确显示。
  • changing 状态下的点击行为:测试当组件处于变化中(changingtrue)时,点击是否会被正确忽略,以防止重复触发 props.onChange

此外,这些问题同样适用于文件中其它局部相似的代码(例如:行 84)。请参考现有的 Switch 组件测试文件(如 src/packages/switch/__test__/switch.spec.tsx)补充对应的测试用例,以提高组件的稳定性和可靠性。

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 60-64: src/packages/switch/switch.tsx#L60-L64
Added lines #L60 - L64 were not covered by tests

Comment on lines +41 to +45
useEffect(() => {
changing && setChanging(false)
}, [value])

const [changing, setChanging] = useState(false)
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

添加状态重置逻辑和状态变量

这段代码添加了两个关键功能:

  1. 使用 useEffectvalue 变化时重置 changing 状态
  2. 引入 changing 状态来跟踪组件的异步变化过程

这是处理异步状态变化的良好实践,但需确保测试覆盖。


🏁 Script executed:

#!/bin/bash
# 检查是否存在测试文件并验证是否覆盖了新增的状态逻辑
echo "查找 Switch 组件的测试文件..."
fd "switch.*test" --type f

Length of output: 79


代码状态变化逻辑已正确引入,但缺少相应测试覆盖

当前修改在 src/packages/switch/switch.tsx 中完成了以下两项关键变更:

  • 使用 useEffect 监听 value 的变化,并在变化时自动将 changing 状态重置为 false
  • 新增 changing 状态变量来追踪组件异步变化过程。

这些改动整体逻辑清晰且符合异步状态处理的良好实践。不过,通过执行检测脚本,目前没有找到针对 Switch 组件新增逻辑的测试文件。请确认或新增相应的单元测试,确保覆盖以下方面:

  • value 变化时,changing 状态能正确重置;
  • 异步状态变化过程中的其它相关交互行为。

Copy link
Collaborator

@oasis-cloud oasis-cloud left a comment

Choose a reason for hiding this comment

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

defaultChecked 无法实现 loading 效果,需要实现 loading 效果得通过受控模式

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 (1)
src/packages/switch/__test__/switch.spec.tsx (1)

65-81: 建议增加更多测试用例以提高覆盖率

当前的测试仅验证了loading图标的显示,建议增加以下测试用例:

  1. 验证当组件处于changing状态时,再次点击不会触发onChange
  2. 验证value变化后changing状态会被重置为false
  3. 测试受控组件模式下的异步加载状态

这些测试将确保新增的异步加载功能在各种场景下都能正确工作。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f4a65e and a5b0f57.

📒 Files selected for processing (1)
  • src/packages/switch/__test__/switch.spec.tsx (2 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/packages/switch/__test__/switch.spec.tsx (2)
src/packages/switch/switch.tsx (1)
  • Switch (16-108)
src/packages/switch/switch.taro.tsx (1)
  • Switch (18-110)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (2)
src/packages/switch/__test__/switch.spec.tsx (2)

4-4: 导入Loading1图标组件以支持新测试用例

导入Loading1组件是为了在新增的loadingIcon测试中使用,这符合组件的异步切换功能增强。


53-63: 改进了disabled测试用例,增强了交互测试

将测试用例更新为异步模式并模拟点击事件,这是一个很好的改进。不仅验证了disabled类名的存在,还验证了禁用状态下的点击行为。

Comment on lines +65 to 81
test('loadingIcon test', async () => {
const testFn = vi.fn()
const { container } = render(
<Switch loadingIcon={<Loading1 />} onChange={testFn} />
)
const el: Element | null = container.querySelector('.nut-switch-button')
if (el) {
await act(() => {
fireEvent.click(el)
})
waitFor(() => {
// 异步
const el = document.getElementsByClassName('.nut-icon')
expect(el.length > 0).toBe(true)
})
}
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

loadingIcon测试中存在选择器错误,且缺少必要的断言

在此测试中发现以下问题:

  1. 第77行选择器.nut-icon中的前导点号会导致选择失败,应该使用nut-icon
  2. waitFor函数没有被await,可能导致测试时序问题
  3. 测试缺少验证onChange回调是否被调用的断言

建议修改如下:

test('loadingIcon test', async () => {
  const testFn = vi.fn()
  const { container } = render(
    <Switch loadingIcon={<Loading1 />} onChange={testFn} />
  )
  const el: Element | null = container.querySelector('.nut-switch-button')
  if (el) {
    await act(() => {
      fireEvent.click(el)
    })
-    waitFor(() => {
+    await waitFor(() => {
      // 异步
-      const el = document.getElementsByClassName('.nut-icon')
+      const iconEl = document.getElementsByClassName('nut-icon')
-      expect(el.length > 0).toBe(true)
+      expect(iconEl.length > 0).toBe(true)
+      expect(testFn).toHaveBeenCalled()
    })
  }
})
📝 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
test('loadingIcon test', async () => {
const testFn = vi.fn()
const { container } = render(
<Switch loadingIcon={<Loading1 />} onChange={testFn} />
)
const el: Element | null = container.querySelector('.nut-switch-button')
if (el) {
await act(() => {
fireEvent.click(el)
})
waitFor(() => {
// 异步
const el = document.getElementsByClassName('.nut-icon')
expect(el.length > 0).toBe(true)
})
}
})
test('loadingIcon test', async () => {
const testFn = vi.fn()
const { container } = render(
<Switch loadingIcon={<Loading1 />} onChange={testFn} />
)
const el: Element | null = container.querySelector('.nut-switch-button')
if (el) {
await act(() => {
fireEvent.click(el)
})
await waitFor(() => {
// 异步
const iconEl = document.getElementsByClassName('nut-icon')
expect(iconEl.length > 0).toBe(true)
expect(testFn).toHaveBeenCalled()
})
}
})

@xiaoyatong xiaoyatong merged commit 6ca45c1 into jdf2e:feat_v3.x Mar 28, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.x Target branch 3.x action:review This PR needs more reviews (less than 2 approvals) size/L
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants