Skip to content

refactor: separate internal debounce and throttle hooks - #565

Merged
mnxmnz merged 2 commits into
toss:v1-basefrom
Antoliny0919:issue-559
Oct 20, 2026
Merged

mnxmnz merged 2 commits into
toss:v1-basefrom
Antoliny0919:issue-559

Conversation

@Antoliny0919

Copy link
Copy Markdown
Contributor

Overview

Closes: #559

Move the soon to be deprecated useDebounce and useThrottle implementations into internal hooks.
Their public APIs will still be deprecated as planned.(I think we only need to handle the deprecation in this issue. -> #537)
Use these internal hooks in the debounce and throttle related hooks(value, callback, state), preserving the existing 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?

Update callback, state, and value hooks to use internal implementations.
Exclude internal hooks from public API JSDoc and export checks.
@changeset-bot

changeset-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 65d5645

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@codecov-commenter

codecov-commenter commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (71c1a07) to head (65d5645).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           v1-base      #565    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files           73        77     +4     
  Lines         2347      2505   +158     
  Branches       754       788    +34     
==========================================
+ Hits          2347      2505   +158     
🚀 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.

@Antoliny0919 Antoliny0919 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I left a few comments with thoughts and questions that came up while working on this.

Most are outside the scope of this PR, so please take a look and share your thoughts whenever you have a chance! 😁

@@ -0,0 +1,93 @@
// Simplified version of https://github.com/toss/es-toolkit/blob/main/src/function/debounce.ts

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I noticed that we have tests for throttle, but none for debounce.

It looks like the debounce and throttle implementations were originally taken from es-toolkit and slightly adapted for simplikit.
Since we maintain this logic ourselves rather than delegating it to an external library, I think it would be good to add tests for debounce too :)

What do you think? I've left it as is for now, since it's outside the scope of this PR!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed, it would be great to have tests for debounce too 👍

Would you like to open a follow-up PR for it? If you'd rather not, no worries. We can track it in an issue 🙌

import { DebouncedFunction } from './debounce.ts';
import { useDebounce } from './useDebounce.ts';

describe('useDebounce', () => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Looking at useDebounce on its own, I think several test cases are missing.
The current tests mainly verify how many times the callback is called.
It would be good to also test whether pending calls are cancelled when the delay or options change, and whether subsequent calls use the latest values when different values are passed in.

I haven't added these tests, since they're outside the scope of this PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Agreed. Testing that pending calls are cancelled when the delay or options change, and that later calls use the latest values, would be valuable 👍

It could go into the same follow-up PR as the debounce tests!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks! The missing tests aren’t urgent, so I’ll add them after the major version is released.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm a little unsure where to put the internal hooks.

I initially considered the existing src/internal directory.
However, hooks would then depend on internal hooks, which in turn depend on usePreservedCallback from the hooks directory:
hooks/useDebouncedCallback → internal/useDebounce → hooks/usePreservedCallback

This doesn't create a circular dependency right now, but it seems like it could lead to one in the future. That's why I created a separate internal directory inside hooks.
However, this approach requires adding exclusions for that directory in parts of CI.
Would it be better to keep them in hooks/internal as they are now, or move them to the existing src/internal directory?
I'd appreciate your thoughts on this! 🙏

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For v1, we'd like to keep the implementation where it is (src/hooks/useDebounce, src/hooks/useThrottle) and keep using it internally. The public useDebounce / useThrottle will only be marked @deprecated in v1 (#537). In v2, we'll stop exporting them and move them under src/_internal/hooks, similar to es-toolkit's src/_internal.

Thank you for thinking this through with us and sharing your ideas! 👍

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you for the clarification!
My understanding is that we'll keep useDebounce and useThrottle in their current locations (src/hooks/useDebounce and src/hooks/useThrottle), and hooks such as useThrottledCallback and useThrottledValue will continue referencing them as before.

For v1, the only change needed is to add @deprecated annotations to indicate that useDebounce and useThrottle will be removed from the public API in v2.

However, the current code references the implementations that were moved under _internal, and those changes have already been merged, so I'm not sure whether I've understood the plan correctly.

Is this something you plan to address as part of #537?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Once I have a clearer understanding of the scope, I think I can work on #537 tomorrow 👍

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Currently, only the Callback hooks take all arguments in a single object, unlike the Value and State hooks. What do you think about accepting only leading and trailing in an options object, consistent with the other hooks?

This would be a breaking change, but I think it's worth addressing as we prepare for a major release. Users familiar with the Value or State hooks would likely expect the corresponding Callback hooks to have a similar interface.

Wouldn't making these interfaces consistent make the API more predictable for users?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We like this idea, and it matches what we discussed in #530. Since #537 already revisits the Callback hooks' signatures, we'll handle it there.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sounds good! I'm not sure whether this should be included in #537, but I think it just needs to be done before v1 is released.

@Antoliny0919

Copy link
Copy Markdown
Contributor Author

I didn't add a changeset since this doesn't change the public API or behavior. Please let me know if one is needed 👍

@Antoliny0919
Antoliny0919 marked this pull request as ready for review October 15, 2026 14:55

@mnxmnz mnxmnz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for working on this! 👍 👍 👍

As you mentioned, your questions are outside the scope of this PR, so we'll discuss them among the maintainers first and follow up here with a summary. It would be great to continue the conversation from there.

Thanks again for raising these questions and thinking them through with us! 🙌

@mnxmnz
mnxmnz merged commit 1a85542 into toss:v1-base Oct 20, 2026
19 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.

3 participants