Skip to content
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

fix: change not trigger on Date #734

Merged
merged 1 commit into from
Nov 13, 2024
Merged

fix: change not trigger on Date #734

merged 1 commit into from
Nov 13, 2024

Conversation

zombieJ
Copy link
Member

@zombieJ zombieJ commented Nov 13, 2024

Date 对象的数据在闭包里,equals 无法检测降级一下:

fix ant-design/ant-design#51611

Summary by CodeRabbit

  • 新功能

    • 更新了 Field 组件的值比较逻辑,简化了值更新的触发条件。
  • 错误修复

    • 移除了不必要的测试用例,确保只有在输入值发生变化时才触发回调。
  • 文档

    • 更新了测试用例的组织结构和注释,提升了可读性和清晰度。

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Copy link

vercel bot commented Nov 13, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
field-form ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 13, 2024 8:12am

Copy link

coderabbitai bot commented Nov 13, 2024

Walkthrough

此拉取请求对 Field 组件的逻辑进行了修改,特别是在 getControlled 方法中,将 newValuevalue 的比较从深度相等检查 isEqual(newValue, value) 更改为严格相等检查 newValue !== value。此外,测试文件也进行了调整,包括删除了一些测试案例并添加了新的测试用例,以增强对表单行为的验证。

Changes

文件路径 更改摘要
src/Field.tsx 修改 getControlled 方法的值比较逻辑,从深度相等检查改为严格相等检查。
tests/control.test.tsx 删除了一个测试用例,保留了两个现有测试用例,主要关注表单的渲染和必填字段规则验证。
tests/field.test.tsx 添加了新测试用例,验证日期输入字段的行为,移除了与之前测试方法相关的注释,增强了测试框架的互动性。
tests/legacy/field-props.test.tsx 更新了 InfoField 的导入语句,重构了归一化测试用例的结构,新增了两个测试用例以验证输入值的处理。

Assessment against linked issues

目标 已解决 解释
修复表单无法获取正确值的问题 (#51611)

Possibly related PRs

  • fix: change #731: 此拉取请求也修改了 Field 组件中的 getControlled 方法,专注于通过防止在值未更改时的不必要调度来优化值更新,这与主拉取请求中关于值比较逻辑的更改密切相关。

Poem

🐇 在田野间跳跃欢快,
逻辑更新真精彩!
深度比较已不再,
严格相等新风采。
测试用例添新彩,
表单行为更明了,
兔子心中乐开怀! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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 resolve resolve all the CodeRabbit review comments.
  • @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.

Copy link

codecov bot commented Nov 13, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.44%. Comparing base (e5738d4) to head (57cd445).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #734   +/-   ##
=======================================
  Coverage   99.44%   99.44%           
=======================================
  Files          18       18           
  Lines        1256     1256           
  Branches      314      310    -4     
=======================================
  Hits         1249     1249           
  Misses          7        7           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

🧹 Outside diff range and nitpick comments (4)
tests/field.test.tsx (2)

4-7: 需要清理未使用的导入

代码中导入了 InputgetInput,但在当前测试文件中并未使用。如果这些导入确实不需要,建议将其删除以保持代码整洁。

建议应用以下修改:

import { act, fireEvent, render } from '@testing-library/react';
-import { Input } from './common/InfoField';
-import { getInput } from './common';
import timeout from './common/timeout';
🧰 Tools
🪛 eslint

[error] 5-5: 'Input' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 6-6: 'getInput' is defined but never used.

(@typescript-eslint/no-unused-vars)


44-75: 测试用例设计合理,建议增加更多边界场景测试

测试用例很好地验证了日期变更的核心功能,符合 #51611 issue 的修复目标。代码结构清晰,使用了正确的异步测试模式。

建议考虑添加以下测试场景:

  1. 验证相同日期值的处理
  2. 测试日期对象为 null 的情况
  3. 添加错误处理测试用例

建议添加如下测试用例:

// 测试相同日期值
it('should not trigger change for same date value', async () => {
  const onValuesChange = jest.fn();
  const fixedDate = new Date('2024-01-01');
  
  const MockDateInput = (props: { onChange?: (val: Date) => void }) => (
    <button onClick={() => props.onChange?.(fixedDate)}>
      Mock
    </button>
  );

  const { container } = render(
    <Form onValuesChange={onValuesChange}>
      <Field name="date">
        <MockDateInput />
      </Field>
    </Form>,
  );

  // 连续触发两次相同的日期
  fireEvent.click(container.querySelector('button'));
  await act(async () => {
    await timeout();
  });
  
  fireEvent.click(container.querySelector('button'));
  await act(async () => {
    await timeout();
  });
  
  expect(onValuesChange).toHaveBeenCalledTimes(1);
});
tests/legacy/field-props.test.tsx (1)

77-89: 建议改进normalize回调的类型安全性

当前的normalize回调函数使用了可选链操作符,建议通过TypeScript类型定义来增强类型安全性。

建议按照以下方式改进:

-  normalize={value => value?.replace(/\D/g, '') || undefined}
+  normalize={(value: string | undefined): string | undefined => 
+    value ? value.replace(/\D/g, '') : undefined
+  }
src/Field.tsx (1)

Line range hint 623-629: 建议添加相关测试用例

为确保 Date 对象的处理逻辑正确,建议添加专门的测试用例。

建议添加以下测试场景:

  1. Date 对象值变更的情况
  2. Date 对象值不变的情况
  3. 其他复杂对象类型的处理
// 建议添加的测试用例
it('should handle Date object value changes correctly', () => {
  const onChange = jest.fn();
  const wrapper = mount(
    <Form>
      <Form.Item name="date">
        <DatePicker onChange={onChange} />
      </Form.Item>
    </Form>
  );
  
  // 测试日期变更
  const newDate = new Date();
  wrapper.find('DatePicker').simulate('change', newDate);
  expect(onChange).toHaveBeenCalled();
  
  // 测试日期不变
  wrapper.find('DatePicker').simulate('change', newDate);
  expect(onChange).toHaveBeenCalledTimes(1);
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e5738d4 and 57cd445.

📒 Files selected for processing (4)
  • src/Field.tsx (1 hunks)
  • tests/control.test.tsx (0 hunks)
  • tests/field.test.tsx (2 hunks)
  • tests/legacy/field-props.test.tsx (2 hunks)
💤 Files with no reviewable changes (1)
  • tests/control.test.tsx
🧰 Additional context used
🪛 eslint
tests/field.test.tsx

[error] 5-5: 'Input' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 6-6: 'getInput' is defined but never used.

(@typescript-eslint/no-unused-vars)

🪛 Biome
tests/legacy/field-props.test.tsx

[error] 64-64: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (2)
tests/legacy/field-props.test.tsx (1)

4-4: 导入语句修改正确!

导入语句的更改符合新增测试用例的需求,同时保持了代码的清晰度。

src/Field.tsx (1)

Line range hint 623-629: 值比较逻辑的改变需要仔细验证

isEqual 深度比较改为 !== 严格不等比较确实可以解决 Date 对象的问题,但这个改动可能会影响其他复杂对象类型的处理。

建议:

  1. 添加对 Date 对象的专门处理逻辑
  2. 或者在比较之前对 Date 对象进行标准化处理
-if (newValue !== value) {
+// 为 Date 对象添加特殊处理
+const isDateValue = newValue instanceof Date && value instanceof Date;
+if (isDateValue ? newValue.getTime() !== value.getTime() : !isEqual(newValue, value)) {
   dispatch({
     type: 'updateValue',
     namePath,
     value: newValue,
   });
 }

Comment on lines +58 to +75
describe('normalize', () => {
it('basic', async () => {
const form = React.createRef<FormInstance>();
const { container } = render(
<div>
<Form ref={form}>
<Field name="normal" normalize={v => v && v.toUpperCase()}>
<Input />
</Field>
</Form>
</div>,
);

await changeValue(getInput(container), 'a');
await changeValue(getInput(container), 'a');

expect(form.current?.getFieldValue('normal')).toBe('A');
expect(getInput(container).value).toBe('A');
});
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

建议补充Date对象规范化(normalize)的测试用例

经检查,项目中已有基本的Date对象变更检测测试(在field.test.tsx中),但缺少针对Date对象规范化的测试场景。建议添加以下测试场景:

  • Date对象的格式转换
  • 无效日期的处理
  • 日期范围的规范化
🔗 Analysis chain

测试用例结构清晰,建议补充Date对象相关测试

测试用例很好地验证了基本的值规范化功能。考虑到此PR主要解决Date对象的变更检测问题,建议添加专门针对Date对象的测试用例。

运行以下脚本检查是否存在其他Date相关的测试:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 搜索项目中与Date对象相关的测试
rg -t tsx -t ts "new Date\(" "test"

Length of output: 63


Script:

#!/bin/bash
# 搜索项目中与Date对象相关的测试,使用正确的文件类型参数
rg "new Date\(" tests/

Length of output: 85


Script:

#!/bin/bash
# 搜索测试文件中可能包含日期相关的测试用例
rg -i "date|moment" tests/

Length of output: 13344


Script:

#!/bin/bash
# 查找测试目录下所有测试文件
fd -e ts -e tsx -e js -e jsx . tests/

Length of output: 816


Script:

#!/bin/bash
# 查看field.test.tsx中的Date相关测试用例的具体实现
rg -A 10 "date type as change" tests/field.test.tsx

Length of output: 336

🧰 Tools
🪛 Biome

[error] 64-64: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

@zombieJ zombieJ merged commit 2c0fa4b into master Nov 13, 2024
12 checks passed
);

await changeValue(getInput(container), 'bamboo');
expect(fn).toHaveBeenCalledTimes(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

为啥把,执行 onChange,不调用 onValueChange 的 test 给删了?

Copy link
Member Author

Choose a reason for hiding this comment

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

挪了一个位置,这个测试用例之前放错地方了

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.

v5.22.0,Form.Item设置了trigger后表单无法获取正确的值
2 participants