[@mantine/hooks] use-intersection: Accept a ref object for the root option - #9054
Open
h-harsh wants to merge 1 commit into
Open
[@mantine/hooks] use-intersection: Accept a ref object for the root option#9054h-harsh wants to merge 1 commit into
h-harsh wants to merge 1 commit into
Conversation
…ption Closes mantinedev#9026 `useIntersection`'s `root` option previously only accepted a resolved `Element`, so the idiomatic React source (a ref) could not be used directly: `ref.current` is `null` on the first render and reading it during render was fragile. The documented usage example relied on that fragile `root: containerRef.current` pattern. `root` now also accepts a `RefObject<Element | null>`. The observer is created inside a `useEffect` (after refs are committed), so the ref's `current` is resolved once the element is mounted — no throwaway viewport-rooted observer and no `.current`-during-render read. Passing a resolved `Element` continues to work unchanged. - Widen the option type via new `UseIntersectionOptions` (exported). - Resolve a ref object to its element before constructing the observer. - Add the hook's first test file (root resolution, viewport fallback, entry updates, cleanup, and an end-to-end render proving the ref root resolves despite child-before-parent ref attachment order). - Update docs and the usage demo to pass the ref directly.
h-harsh
force-pushed
the
feat/use-intersection-ref-root
branch
from
July 12, 2026 19:23
a56105d to
77d260a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #9026
useIntersection'srootoption previously only accepted a resolvedElement, so the idiomatic React source — a ref — couldn't be used directly.ref.currentisnullon the first render and reading it during render is fragile, which is exactly what the documented usage example did (root: containerRef.current).This mirrors #9031, which added ref support to
useScrollSpy'sscrollHost.The catch (why this isn't a one-liner)
useScrollSpyattaches its listener inside auseEffect, soref.currentis already populated when it runs.useIntersectionis different: it built theIntersectionObserversynchronously inside the target's callback ref. Because React attaches child refs before their parent's, arootref is stillnullat that moment — so naively resolvingroot.currentthere would reproduce the exact bug, just relocated.The fix moves observer creation into a
useEffect(runs after all refs are committed), tracking the observed element in state via the callback ref. As a bonus this removes the old throwaway viewport-rooted observer + extra render that the previousroot: ref.currentpattern caused.Changes
UseIntersectionOptions(root?: IntersectionObserverInit['root'] | React.RefObject<Element | null>).Elementis unchanged.root: containerRef).Notes
Element/ no-arg callers are unaffected.Verification
use-intersectiontests: 11 passingtsc --noEmitclean,oxlintclean, formatted@mantine/hooksbuilds (incl..d.tsgeneration)