Fix spurious React 18.3 ref warning in AnimatePresence non-popLayout mode#3754
Fix spurious React 18.3 ref warning in AnimatePresence non-popLayout mode#3754mattgperry wants to merge 1 commit into
ref warning in AnimatePresence non-popLayout mode#3754Conversation
…mode PopChild read children.props.ref unconditionally. In React 18.3, creating an element with a ref prop installs a warning getter on element.props.ref, so reading it fired "`ref` is not a prop" even though the composed ref is only used when popping the child out (pop !== false). Only read it then. Fixes #3745 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Greptile SummaryGuards the
Confidence Score: 5/5Safe to merge — the change is a single conditional guard with no behavioural impact on popLayout mode and a clear regression test verifying the fix. The fix is minimal and targeted: it moves the children.props.ref read behind the same pop !== false gate that already controls the cloneElement call and the useInsertionEffect body. useComposedRefs handles undefined gracefully (the PossibleRef type explicitly includes undefined), and the composed ref is never attached to any element in non-popLayout mode both before and after this change. The new test file correctly isolates the module-level warned once flag and directly asserts the failure condition. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant AP as AnimatePresence
participant PC as PresenceChild
participant Pop as PopChild
participant React as React 18.3
AP->>PC: "render child (mode="sync"|"wait")"
PC->>Pop: "pop={false}"
Note over Pop: pop !== false → false<br/>childRef = undefined (no props.ref access)
Pop-->>React: no warning getter triggered
Pop->>AP: return children directly (no cloneElement)
AP->>PC: "render child (mode="popLayout")"
PC->>Pop: "pop={true}"
Note over Pop: pop !== false → true<br/>childRef = children.props.ref
Pop->>React: "cloneElement(children, { ref: composedRef })"
Reviews (1): Last reviewed commit: "Fix spurious React 18.3 ref warning in A..." | Re-trigger Greptile |
Bug
AnimatePresencein any mode other thanpopLayout(i.e. the defaultsyncandwait) emits a React warning when its child has aref:Minimal repro:
Cause
PopChildreadchildren.props?.refunconditionally on every render:In React 18.3, creating an element with a
refprop installs a warning getter onelement.props.ref(defineRefPropWarningGetter). Any access to that getter fires the warning. The composed ref is only ever used in thepop !== falsebranch (React.cloneElement(children, { ref: composedRef })), so in non-popLayout mode the read is pointless yet still trips the warning.The
[object Object]display name appears becausemotion.*components areforwardRefobjects (not functions), so React's element validator stringifies the raw object as the display name.This is distinct from the earlier React 19
popLayoutref fixes (v12.23.16, v12.24.5) — it affects non-popLayout mode under React 18.3.Fix
Only read
children.props.refwhen the ref is actually used (pop !== false):popLayoutbehaviour is unchanged — the ref is still read and composed when popping.Test
Added
pop-child-ref.test.tsx, which renders anAnimatePresence(default mode) around a ref'dmotion.divand asserts no`ref` is not a propwarning is logged. It lives in its own file so React's module-level "warned once" flag starts fresh.mainfor the right reason (warning fired fromPopChild→PresenceChild→AnimatePresence).framer-motionclient suite passes (776 tests); allAnimatePresence/PopChild/use-presencesuites pass.Fixes #3745
🤖 Generated with Claude Code