Skip to content

refactor(useRefEffect): Improve useRefEffect hook by adding generic types in docs and strict null check in implementation#273

Merged
kimyouknow merged 9 commits intotoss:mainfrom
wo-o29:refactor/fix-userefeffect-null-check-and-generic
Mar 13, 2026
Merged

refactor(useRefEffect): Improve useRefEffect hook by adding generic types in docs and strict null check in implementation#273
kimyouknow merged 9 commits intotoss:mainfrom
wo-o29:refactor/fix-userefeffect-null-check-and-generic

Conversation

@wo-o29
Copy link
Contributor

@wo-o29 wo-o29 commented Sep 13, 2025

Overview

This PR introduces two distinct improvements to the useRefEffect hook:

  1. Documentation and interface now include a generic type parameter, enhancing type safety and flexibility when using the hook with different HTMLElement types. This change improves developer experience by providing accurate typing information in the docs and type signatures.

  2. The implementation has been updated to perform a strict null check (element === null) rather than a loose check. This strengthens type narrowing in TypeScript, ensuring that the callback is only called when a valid element is set, and avoids potential bugs related to falsy values.

Together, these changes make the hook safer to use and better documented without changing its external behavior.

Checklist

  • Did you write the test code?
  • Have you run yarn run fix to format and lint the code and docs?
  • Have you run yarn run test:coverage to make sure there is no uncovered line?
  • Did you write the JSDoc?

Copilot AI review requested due to automatic review settings September 13, 2025 07:11
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR enhances the useRefEffect hook by adding generic type parameters to improve type safety and strengthening the null check implementation. The changes improve developer experience through better TypeScript typing while maintaining the same external behavior.

  • Added generic type parameter <E extends HTMLElement> to the hook interface for better type safety
  • Updated null check from loose equality (== null) to strict equality (=== null) for more precise type narrowing
  • Updated documentation to reflect the new generic type interface

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/hooks/useRefEffect/useRefEffect.ts Strengthened null check from loose to strict equality
src/hooks/useRefEffect/useRefEffect.md Updated interface documentation to include generic type parameter
src/hooks/useRefEffect/ko/useRefEffect.md Updated Korean documentation to match generic type interface

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

cleanupCallbackRef.current = () => {};

if (element == null) {
if (element === null) {
Copy link

Copilot AI Sep 13, 2025

Choose a reason for hiding this comment

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

The strict null check element === null will not catch undefined values, which could cause the callback to be executed with undefined. The original loose equality check == null was correct as it handles both null and undefined cases. This change could introduce bugs when the element is undefined.

Suggested change
if (element === null) {
if (element == null) {

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since instance is of type T | null as in React CallbackRef Type, I don't think we need to check for undefined. What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

You're right! — since the type is T | null, === null works correctly here.

That said, our codebase uses == null as the convention (see mergeRefs, mergeProps, debounce, etc.), so how about keep it consistent and revert to == null??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it would be better to stick to the existing conventions!

@codecov-commenter
Copy link

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (5bdb4ff) to head (a8ecfc4).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #273   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           37        37           
  Lines         1093      1093           
  Branches       324       324           
=========================================
  Hits          1093      1093           
🚀 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.

```ts
function useRefEffect(
callback: (element: Element) => CleanupCallback | void,
function useRefEffect<E extends HTMLElement>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

On the generic naming — I agree that the current source Element shadows the global DOM type, so a rename makes sense

However, our convention avoids abbreviations, so E might not be the best fit. What do you think about using a full name likeTargetElement or RefElement instead? Or if you have another idea, happy to hear it!

If we go with a rename, it'd be great to update both the source and docs together so they stay in sync.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used abbreviations based on the useLongPress and mouseDoubleClick documentation, but both hooks are now deprecated🤔

RefElement looks good :)

We will update both the source code and documentation!

@kimyouknow
Copy link
Collaborator

Once those are adjusted + rebase on latest main + changeset (yarn changeset → patch, guide), we're good to merge!

@wo-o29 wo-o29 requested a review from zztnrudzz13 as a code owner March 3, 2026 15:58
@kimyouknow
Copy link
Collaborator

@wo-o29 This is a legitimate improvement:

  • Generic rename (ElementE) resolves global DOM type shadowing ✅
  • === null strict equality aligns with project conventions ✅
  • Clean diff, no functional changes

A couple of items before merging:

  1. Abbreviation in docs: Please avoid abbreviations like "desc" — use full words ("description") per our documentation style. Check the docs changes for any abbreviated terms.

  2. Add a changeset (yarn changeset) for the === null change (technically a behavioral contract tightening, even if functionally equivalent).

  3. Rebase on latest main to resolve conflicts.

Once these are addressed, we'll merge right away! ✅

@kimyouknow kimyouknow merged commit ffc61bb into toss:main Mar 13, 2026
11 checks passed
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.

4 participants