Skip to content

feat(hooks): add 'useIsMounted'#244

Closed
sukvvon wants to merge 1 commit into
toss:mainfrom
sukvvon:feat/add-useIsMounted
Closed

feat(hooks): add 'useIsMounted'#244
sukvvon wants to merge 1 commit into
toss:mainfrom
sukvvon:feat/add-useIsMounted

Conversation

@sukvvon
Copy link
Copy Markdown
Contributor

@sukvvon sukvvon commented May 30, 2025

Overview

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?

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 30, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (bea638d) to head (49b5df8).
⚠️ Report is 82 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #244   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           33        34    +1     
  Lines          836       847   +11     
  Branches       254       258    +4     
=========================================
+ Hits           836       847   +11     
🚀 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.

@seungrodotlee
Copy link
Copy Markdown
Contributor

According to our design principles, we might need to carefully consider whether providing this hook is the right approach.

@sukvvon
Copy link
Copy Markdown
Contributor Author

sukvvon commented Jun 2, 2025

@seungrodotlee

Thank you for raising that point — I completely agree with the importance of respecting React’s lifecycle and avoiding interference.

That said, I believe useIsMounted aligns with that principle rather than violating it. It doesn’t attempt to override or short-circuit any part of React’s lifecycle; instead, it acts as a guard mechanism for asynchronous side effects, helping prevent updates to unmounted components — a common source of memory leaks and hard-to-trace bugs.

In fact, this pattern complements React’s lifecycle by acknowledging the asynchronous nature of effects, especially in environments where race conditions or delayed executions (e.g., setTimeout, fetch, or requestAnimationFrame) are involved.

While it’s true that React encourages effects to be scoped correctly, in practice developers still face scenarios where external timing or delayed callbacks can lead to unintended updates. useIsMounted simply provides a safe, minimal way to check component presence without mutating state or interfering with React’s render cycle.

So rather than introducing lifecycle interference, this hook serves as a passive safety utility — one that aligns with React’s declarative philosophy by helping avoid imperative leaks.

@kimyouknow
Copy link
Copy Markdown
Collaborator

@sukvvon Thank you for the clean implementation — the code quality is excellent (SSR-safe, usePreservedCallback, 100% coverage).

Before merging, we'd like to discuss one architectural concern:

React 18 removed the "setState on unmounted component" warning (reactwg/react-18#82). The React team's position is that isMounted checks don't solve actual memory leaks, and the recommended approach is AbortController + useEffect cleanup.

That said, useIsMounted is still provided by libraries like usehooks-ts, and there are valid use cases beyond just suppressing warnings.

We'd like to align with @zztnrudzz13 on whether this fits our library scope before proceeding. Will follow up soon!

@zztnrudzz13
Copy link
Copy Markdown
Collaborator

Following up here — after discussing internally, we’ve decided to close this PR.

While the implementation is solid, useIsMounted is based on a pattern that the React team generally discourages. isMounted checks don’t actually prevent memory leaks; they mainly hide the symptom (skipping a state update) rather than addressing the root cause. In most cases, the recommended approach is to cancel async work or clean up subscriptions properly in useEffect.

Because of this, adding a hook like this would likely result in something we’d eventually mark as deprecated. For that reason, we don’t think it fits well within the long-term direction of this library.

Thanks again for the clean implementation and for taking the time to contribute 🙏

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.

5 participants