Repository navigation
fix(useRefEffect): use the updated callback when dependencies change - #483
Conversation
🦋 Changeset detectedLatest commit: 8828030 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #483 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 69 69
Lines 2233 2242 +9
Branches 718 720 +2
=========================================
+ Hits 2233 2242 +9 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟡 Changes recommended
A new test file uses *.test.tsx naming in a hook folder that already follows the older *.spec.ts convention, and it should be renamed/migrated to match repo conventions.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Fixes a subtle ref-attachment timing issue in useRefEffect where dependency changes could still invoke the previous render’s callback during DOM ref commit, which in turn impacted downstream hooks like useIntersectionObserver.
Changes:
- Reworked
useRefEffectto use a dependency-scoped callback holder so the updated callback is available during ref attachment (before passive effects run). - Added DOM lifecycle regression tests for
useRefEffectand an observer migration regression test foruseIntersectionObserver. - Added a patch changeset documenting the bugfix.
File summaries
| File | Description |
|---|---|
| packages/react-simplikit/src/hooks/useRefEffect/useRefEffect.ts | Creates a new callback holder when deps change and keeps committed callback updates via useEffect to avoid stale callback reads during ref attachment. |
| packages/react-simplikit/src/hooks/useRefEffect/useRefEffect.test.tsx | Adds DOM/ref lifecycle regression coverage for dependency changes, StrictMode behavior, conditional attachment, and Suspense. |
| packages/react-simplikit/src/hooks/useIntersectionObserver/useIntersectionObserver.spec.ts | Adds regression asserting a mounted element is moved to the newly created observer when observer options change. |
| .changeset/fix-ref-effect-callback.md | Patch changeset describing the behavioral fix for dependency changes during ref attachment. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
hyesungoh
left a comment
There was a problem hiding this comment.
Thank you for contribution! 👍 👍
Overview
When
useRefEffectis attached to a DOM element and its dependencies change, React calls the ref before passive effects run. The ref previously read throughusePreservedCallback, whose callback was still from the previous render. For example, changing a dependency fromAtoBrancleanup(A)followed bysetup(A)instead ofsetup(B).This also affects
useIntersectionObserver: changing the root, root margin, or threshold creates a new observer, but the ref can reattach the element to the previous observer.Changes
usePreservedCallbackunchanged and avoid mutating an existing callback holder during render.Validation
The public signature is unchanged. No new dependency is added.
Checklist
yarn test:coveragewith 100% coverage.