Skip to content

fix(useEvent): preserve handler context and improve typings#798

Open
li-jia-nan wants to merge 2 commits into
masterfrom
useEvent-type
Open

fix(useEvent): preserve handler context and improve typings#798
li-jia-nan wants to merge 2 commits into
masterfrom
useEvent-type

Conversation

@li-jia-nan

@li-jia-nan li-jia-nan commented Jul 18, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • 改进
    • 优化事件回调处理:通过稳定函数与内部引用保存最新回调,降低渲染间不必要的更新。
    • 强化类型支持:提供更清晰的多重泛型重载,精确描述回调的 this、参数与返回值;回调可选时正确返回可能的空值。
  • 小优化
    • 调整延迟配置的类型分支表达方式,提升可读性;相关类型标注更直接,行为保持一致。

Copilot AI review requested due to automatic review settings July 18, 2026 00:12
@vercel

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
util Ready Ready Preview, Comment Jul 18, 2026 12:21am

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

React Doctor found no issues. 🎉

⚠️ Warning: .github/workflows/react-doctor.yml is configured incorrectly. See below to fix.

React Doctor compares against master to report only the issues this pull request introduces. This run couldn't complete that comparison (usually a shallow CI checkout with no merge base), so it listed every issue in the changed files, including ones that already existed on master.

Add fetch-depth: 0 to the actions/checkout step in .github/workflows/react-doctor.yml so the checkout includes the history React Doctor needs:

 jobs:
   react-doctor:
     steps:
       - uses: actions/checkout@v5
+        with:
+          fetch-depth: 0

       - uses: millionco/react-doctor@v2

To silence this warning, set silence-missing-baseline-warning: true on the React Doctor action.

Reviewed by React Doctor for commit 0df47f2.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

重构 useEvent 的类型声明与实现:新增显式泛型重载,支持可选回调;使用 useRef 保存最新回调,并通过 useState 创建引用稳定的函数,同时调整 useDelayState 的类型调用方式。

Changes

useEvent 重构

Layer / File(s) Summary
更新类型契约
src/hooks/useEvent.ts
新增 StableHandler 类型,并以泛型重载声明 this、参数元组、返回值及可选回调。
实现稳定回调
src/hooks/useEvent.ts
使用 useRef 保存最新回调,通过 effect 更新 ref,并用 useState 初始化稳定函数调用当前回调。
同步 useDelayState 调用方式
src/hooks/useDelayState.ts
保留 DelayConfig 的互斥字段约束,并在 useEvent 回调参数处直接声明状态值与延迟配置类型。

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant React
  participant useEvent
  participant Callback
  React->>useEvent: 渲染并传入最新 callback
  useEvent->>useEvent: 更新 fnRef.current
  React->>useEvent: 调用稳定函数
  useEvent->>Callback: apply 最新回调与参数
Loading

Possibly related PRs

Suggested reviewers: zombiej

Poem

我是小兔,蹦进稳定函数间,
新回调藏进 ref,旧引用不改变。
类型参数排成队,
可选回调也能应答,
胡萝卜般清晰,代码向前。

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了本次对 useEvent 的上下文保留与类型增强改动。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch useEvent-type

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 refactors the useEvent hook to preserve the this context of the callback function by introducing overloads, a custom StableHandler type, and replacing useCallback with useState. The review feedback identifies a potential TypeScript compilation error under strictNullChecks because the optional callback parameter is passed to React.useRef without allowing undefined in its type parameter.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/hooks/useEvent.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/hooks/useEvent.ts (1)

1-2: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

合并 React 导入语句

建议将 useState 与默认的 React 导入合并,以提升代码整洁度。

♻️ 建议修改
-import React from 'react';
-import { useState } from 'react';
+import React, { useState } from 'react';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/useEvent.ts` around lines 1 - 2, 合并 useEvent.ts 顶部的 React 与
useState 导入,使用单条导入语句保留默认 React 和命名导出 useState,并移除重复的独立导入。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/hooks/useEvent.ts`:
- Around line 24-25: Update the fnRef declaration in useEvent to allow an
undefined callback in its generic type, then move fnRef.current assignment out
of render and into a useLayoutEffect that tracks callback changes. Preserve the
existing stable-handler behavior and use the project’s SSR-safe layout-effect
wrapper if one exists.
- Around line 27-33: 在 useEvent 中构造 stableHandler 时添加类型断言,确保可选链调用推导出的 Result |
undefined 被转换为与重载签名一致的严格 Result 返回类型;若已将泛型重构为单一 T,则改用对应的 unknown 到 T 的断言。
- Around line 4-23: 恢复 useEvent 以单一函数类型泛型 T 为主的泛型契约,确保现有的
useEvent<SetDelayState<T>> 调用继续兼容;在 useEvent 的类型声明和实现中使用
ThisParameterType、Parameters 与 ReturnType 从 T 提取 this、参数及返回值类型,同时保留无参数调用的可选回调与
undefined 返回行为。

---

Nitpick comments:
In `@src/hooks/useEvent.ts`:
- Around line 1-2: 合并 useEvent.ts 顶部的 React 与 useState 导入,使用单条导入语句保留默认 React
和命名导出 useState,并移除重复的独立导入。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2e75365e-989c-4da6-aa1a-c88664e920ee

📥 Commits

Reviewing files that changed from the base of the PR and between 152384e and 9797741.

📒 Files selected for processing (1)
  • src/hooks/useEvent.ts

Comment thread src/hooks/useEvent.ts
Comment thread src/hooks/useEvent.ts Outdated
Comment thread src/hooks/useEvent.ts
@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.74%. Comparing base (152384e) to head (0df47f2).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #798      +/-   ##
==========================================
+ Coverage   86.72%   86.74%   +0.02%     
==========================================
  Files          40       40              
  Lines        1092     1094       +2     
  Branches      395      396       +1     
==========================================
+ Hits          947      949       +2     
  Misses        143      143              
  Partials        2        2              

☔ View full report in Codecov by Harness.
📢 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.

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

✅ Preview is ready!

PR preview ✅ Ready ✅ Ready
🔗 Preview https://react-component-util-preview-pr-798.surge.sh
📝 Commit0df47f2
⏱️ Build time32.682s
📦 Size1.7 MB · 45 files
🪵 LogsView logs
📱 MobileScan to open preview on mobile

↩️ Previous: ⚡️ 0df47f2 · react-component-util-preview-pr-798.surge.sh (open ↗) · 2026-07-18 00:22:04 UTC

🤖 Powered by surge-preview

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src/hooks/useEvent.ts (1)

27-37: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

修复内部实现中残留的 TypeScript 严格模式类型报错

遗留了之前 Review 中指出的两个内部类型隐患,会导致项目在 TypeScript 严格模式下编译报错:

  1. useRef 泛型缺失 | undefined:参数 callback 是可选的(可为 undefined),但传入 useRef 时泛型参数未包含 | undefined,会导致类型不匹配报错。
  2. 实现签名与重载签名不兼容:内部通过 fnRef.current?.apply() 进行可选链调用,推导出的 stableHandler 返回类型包含 | undefined,这与第一个重载签名强制要求的严格返回类型 Result 不兼容,会导致 This overload signature is not compatible with its implementation signature. 的编译报错。

建议为 useRef 补充 | undefined 并在构造 stableHandler 时补充类型断言以严格对齐重载签名。

🐛 推荐的类型修复方案
-  const fnRef = React.useRef<StableHandler<This, Args, Result>>(callback);
+  const fnRef = React.useRef<StableHandler<This, Args, Result> | undefined>(callback);

   useIsomorphicLayoutEffect(() => {
     fnRef.current = callback;
   }, [callback]);

   const [stableHandler] = useState(() => {
-    return function (this: This, ...args: Args) {
-      return fnRef.current?.apply(this, args);
-    };
+    return (function (this: This, ...args: Args) {
+      return fnRef.current?.apply(this, args);
+    } as unknown as StableHandler<This, Args, Result>);
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/hooks/useEvent.ts` around lines 27 - 37, 在 useEvent 的内部实现中,将 fnRef 的
useRef 泛型扩展为 StableHandler<This, Args, Result> | undefined,以匹配可选 callback;同时为
useState 构造的 stableHandler 补充与重载返回类型一致的类型断言,确保 fnRef.current?.apply()
产生的可选返回值不会导致实现签名与重载签名不兼容。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/hooks/useEvent.ts`:
- Around line 27-37: 在 useEvent 的内部实现中,将 fnRef 的 useRef 泛型扩展为
StableHandler<This, Args, Result> | undefined,以匹配可选 callback;同时为 useState 构造的
stableHandler 补充与重载返回类型一致的类型断言,确保 fnRef.current?.apply()
产生的可选返回值不会导致实现签名与重载签名不兼容。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cd452ae5-4d5d-4374-a4b7-0d6e8f8258de

📥 Commits

Reviewing files that changed from the base of the PR and between 9797741 and 0df47f2.

📒 Files selected for processing (2)
  • src/hooks/useDelayState.ts
  • src/hooks/useEvent.ts

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.

2 participants