Repository navigation
refactor(core): useAttachment moves to hooks/, and useFingerScroll keeps its watch through it - #9414
Conversation
useFingerScroll kept its own copy of the attachment lifecycle the other gesture hooks share: follow the node after each commit, release the replaced node and attach the new one, release at unmount. It now calls useAttachment, which takes a node ref (an element's, or the document's) with no change for its callers, so a fix to that lifecycle reaches all three hooks. A new useFingerScroll case pins that the watch lets go of a node it stops following and of its last node at unmount; it fails with either release removed from useAttachment. No behavior changes.
…use it useAttachment keeps an attach function bound to the node a ref holds across commits: release the replaced node, attach the new one, release at unmount. It is a plain React helper, so it moves from gestures/ to hooks/useAttachment.ts (not exported from hooks/index.ts), where hooks outside gestures/ can use it instead of copying it. The gesture-sync depth and useIsUnmountedRef, which only the gesture hooks read, stay in gestures/gestureSync.ts. useGestureRecognizer, usePressTracker and useFingerScroll import from the new homes. No behavior changes; no interaction spec bundles these hooks, so the WebKit job's scope is unchanged.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
There was a problem hiding this comment.
This looks ready to approve: useFingerScroll now shares useAttachment's attach-and-release lifecycle with the other gesture hooks, with no public API or behavior change, and the new test case fails if either release is removed from the shared helper.
One small fix for the description: its "Intended invariant" quotes INV3 of the React component runtime record with wording that record does not contain; the lifecycle maps to INV5 and INV6, and the single-owner direction to INV16.
[Automated review]
On main, after #8360.
useDragToSnapPoints(#8658) calls the moved hook once this lands.Maintainer impact
Three hooks each keep an attach function bound to the node a ref holds across commits: release the replaced node, attach the new one, release at unmount.
useGestureRecognizerandusePressTrackershareuseAttachmentfor it;useFingerScrollkept its own copy, anduseDragToSnapPoints(#8658) needs the same lifecycle outsidegestures/. A fix to one copy could miss the other.Intended invariant
architecture:react-component-runtimeINV3: a hook syncs with the DOM node a ref holds after each commit, re-attaches when that node or its key changes, does nothing on a commit that changes neither, and releases at unmount. One helper owns that lifecycle.Change
useFingerScrollkeeps its finger-scroll watch throughuseAttachment, which now takes a node ref, the document's included, instead of its own two Effects.useAttachmentmoves tohooks/useAttachment.ts, not exported fromhooks/index.ts, where hooks outsidegestures/can use it. The gesture-sync depth anduseIsUnmountedRef, which only the gesture hooks read, stay ingestures/gestureSync.ts.Evidence
useFingerScrollcase pins that the watch lets go of a node it stops following, and of its last node at unmount. It passes on the copy and fails with either release removed from it; after the change it fails with either release removed fromuseAttachment(7 failing cases each), so the lifecycle has one place to break.Scope
Testing
Local gates at 4ea3e24, two commits on main (7 files, +171/−86):
pnpm test:ui(the UI tests of Core, Lab and Richtext): 714 files, 17,785 tests passed. The tests that load the changed files, by their imports and the pages they bundle, areuseFingerScroll.test.tsxanduseGestureRecognizer.test.tsx, both in that run; no browser spec loads them.pnpm build: 843 files passed; onlyrelease/cache.test.mjs's two cases fail, as on main (fix(cli): a crashed run's release install is recognized by the Node it ran on, whatever its name #8520). The gesture-free-entries and WebKit-scope tests pass.tsc --project packages/core/tsconfig.json --noEmit, strict ESLint, Prettier, the private-attribute baseline,check:repo,check:knowledge,check:changesetsand changeset coverage: clean.