Skip to content

Conversation

@welkinwong
Copy link
Contributor

Problem Description

This PR fixes two distinct unresponsiveness issues in the useTrackerSuspense hook:

  1. Unresponsiveness to data changes in StrictMode (dev only) - In development environment with StrictMode enabled, components fail to respond properly when data changes
  2. Unresponsiveness after query/dependencies changes - UI becomes unresponsive after query conditions change (for the no deps version) or dependencies change (for the with deps version)

Fixes Included

Commit 1: fix(useTrackerSuspense): fix unresponsiveness under StrictMode (dev only)

Resolved the issue where components don't respond to data changes in React StrictMode (dev only)

Commit 2: fix(useTrackerSuspense): fix unresponsiveness after query conditions change

Fixed the unresponsiveness that occurs after query conditions change (no deps version) or dependencies change (with deps version)

Testing & Verification

  • Verified responsiveness to data changes in StrictMode environment
  • Tested various query condition and dependency change scenarios to confirm issues are resolved
  • Ensured existing functionality remains unaffected

Impact

  • Only affects the behavior of useTrackerSuspense hook
  • Provides better debugging experience in development StrictMode

// To avoid this, check the `timeout` to ensure cleanup only occurs after unmount.
if (refs.cleanupTimoutId) {
clearTimeout(refs.cleanupTimoutId)
delete refs.cleanupTimoutId
Copy link
Member

Choose a reason for hiding this comment

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

Using the delete operator in V8 (the engine behind Node.js and Chrome) is generally not good for performance, especially in long-running or high-throughput applications.

When you use delete obj.key, V8 must change the object’s internal structure . This invalidates V8’s optimizations and forces the engine to fall back to slower property storage mechanisms .

Set it to undefined instead

refs:
https://phillcode.hashnode.dev/javascript-delete
https://alexanderobregon.substack.com/p/what-happens-when-you-delete-properties

Run this benchmark

Image

Copy link
Contributor Author

@welkinwong welkinwong Oct 25, 2025

Choose a reason for hiding this comment

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

👍 Okay, I'll make the changes here


refs.isMounted = false
return () => {
refs.cleanupTimoutId = setTimeout(() => {
Copy link
Member

Choose a reason for hiding this comment

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

Why settimeout(0) instead of processNextTick?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The code at line 149 is only called by the client. The server directly uses resolveAsync:

export const useTrackerSuspenseServer: typeof useTrackerSuspenseClient = (key, reactiveFn) => {
  return resolveAsync(key, Tracker.nonreactive(reactiveFn))
}

@Grubba27 Grubba27 merged commit 6f89c91 into meteor:feature/4.0.1 Oct 31, 2025
2 checks passed
@Grubba27 Grubba27 mentioned this pull request Oct 31, 2025
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