fix: trigger onChange twice when using IME input
This PR addresses issue #77 .
The same solution as https://github.com/react-component/input/pull/61.
Summary by CodeRabbit
Bug Fixes
- 改进了文本框对输入法(IME)输入事件的处理机制。系统现已能够准确识别不同的输入事件来源,防止在输入法组合转换过程中发生意外的状态更新,显著增强了中文、日文等多语言输入场景下的稳定性和用户体验。
Walkthrough
在 src/TextArea.tsx 中为 triggerChange 方法添加了 ChangeEventInfo 参数以区分事件源,并在组合事件结束时添加了条件守卫以防止意外的状态变化。同时在 src/interface.ts 中新增导出接口 ChangeEventInfo。
Changes
| 聚合类 / 文件 | 改动摘要 |
|---|---|
新增类型定义 src/interface.ts |
新增导出接口 ChangeEventInfo,包含 source 字段,用于标识变化事件的来源('compositionEnd' | 'change') |
核心逻辑改动 src/TextArea.tsx |
扩展 triggerChange 方法签名以接受 info: ChangeEventInfo 参数;在三个调用点传播 info 对象;在 compositionEnd 流程中添加守卫条件,当 info.source === 'compositionEnd' 时跳过值更新;调整导入顺序 |
Sequence Diagram(s)
sequenceDiagram
participant User
participant TextArea as TextArea Component
participant triggerChange as triggerChange
participant onChange as onChange Handler
User->>TextArea: Composition End Event
TextArea->>triggerChange: Call with info.source='compositionEnd'
alt source === 'compositionEnd'
triggerChange->>triggerChange: Skip value update (guard)
end
triggerChange->>onChange: Emit change event
User->>TextArea: Regular Change Event
TextArea->>triggerChange: Call with info.source='change'
triggerChange->>triggerChange: Process value update
triggerChange->>onChange: Emit change event
Estimated code review effort
🎯 2 (Simple) | ⏱️ ~8 分钟
- 需要验证 triggerChange 的三个调用点是否都正确传递了 info 参数
- 确认 compositionEnd 的守卫条件逻辑是否完整解决组合事件重复触发问题
- 检查 ChangeEventInfo 接口的类型约束是否完整且与实际使用场景匹配
Possibly related issues
- react-component/textarea#77:该 PR 直接实现了该 issue 提出的解决方案——通过引入 ChangeEventInfo 类型和在 triggerChange 中添加守卫条件来防止 compositionEnd 时的重复 onChange 触发
Poem
🐰 小兔蹦跳来修复,
compositionEnd 不再双声鸣;
info 信使来传话,
事件源头清晰分,
文本框稳稳当当~
Pre-merge checks and finishing touches
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The pull request title accurately describes the main change: triggering onChange twice when using IME input. This directly relates to the core functionality added in the changeset, which involves tracking the source of change events (compositionEnd vs change) and handling them appropriately. |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
📜 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 17f20cd4fe2b9b4efd3eb624fba7143d9ace76a3 and ad936811b5a424b0c1b4c6bfabe959d8735bf51b.
📒 Files selected for processing (2)
-
src/TextArea.tsx(4 hunks) -
src/interface.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/TextArea.tsx (1)
src/interface.ts (1)
ChangeEventInfo(48-50)
🔇 Additional comments (5)
src/interface.ts (1)
47-50: 新增的 ChangeEventInfo 接口定义合理!接口清晰地定义了事件源的类型约束,用于区分 IME 输入的不同阶段,这是解决双重触发问题的关键。
src/TextArea.tsx (4)
10-10: 导入变更正确!正确引入了
ChangeEventInfo类型用于区分事件源。Also applies to: 15-15
104-110: 函数签名扩展合理!为
triggerChange添加info参数使函数能够根据事件源执行不同的逻辑,这是实现修复的核心改动。
149-149: 调用点更新完整!两个调用点都正确传递了
info参数:
- compositionEnd 时传递
{ source: 'compositionEnd' }- change 事件时传递
{ source: 'change' }参数传递准确且一致。
Also applies to: 154-154
129-131: 补充测试:验证 IME 输入时 onChange 调用计数固卫条件逻辑正确,但现有测试缺少关键验证。当前测试只验证最终值是否正确截断,未验证 onChange 调用次数的去重。
建议补充测试用例,在 tests/index.spec.tsx 中添加:
- 验证 IME 输入超过 maxLength 时,onChange 仅被调用一次(不是两次)
- 验证正常非 IME 输入不受影响,onChange 仍正常触发
当前已有的功能测试(exceedFormatter 值截断正确)不足以证明去重逻辑生效。
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
Summary of Changes
Hello @SocietyNiu, I'm Gemini Code Assist[^1]! 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 resolves a bug where the onChange event was being triggered twice when using IME input in the TextArea component. The fix involves distinguishing between compositionEnd and regular change events to prevent duplicate triggers, ensuring that the onChange event is only fired once per actual change.
Highlights
-
Issue Fix: This PR addresses issue #77, which involves the
onChangeevent being triggered twice when using IME input in the TextArea component. -
Solution: The solution implemented is the same as the one used in react-component/input#61, which likely involves handling the
compositionEndevent to prevent duplicateonChangetriggers. -
Code Changes: The changes include adding a
sourcefield to theChangeEventInfointerface to differentiate betweencompositionEndand regularchangeevents. ThetriggerChangefunction is updated to include this source information, and theonCompositionEndhandler is modified to trigger change withcompositionEndsource. -
Event Handling: The
onInternalChangehandler now also includes the source information aschange.
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 :thumbsup: and :thumbsdown: 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.
[^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.
Code Review
This pull request aims to fix an issue where
onChangeis triggered twice when using an IME by introducing asourceto the change event. While the approach is sound, the current implementation has a logical flaw. The fix works correctly whenmaxLengthis not a factor, but it fails to prevent the double trigger whenmaxLengthis active and exceeded, as the new logic is bypassed. I've provided a suggestion to correct this logic to ensureonChangeis only fired once in all scenarios.
The expected result is for OnChange to be triggered twice when the input exceeds the maxLength. As the image shows, the whole string will be outputted the first time and the second time there will be a cut string. The implementation within rl-input is the same. Users should manage the difference.