Fix AnimatePresence exit animations with Radix UI asChild#3460
Merged
mattgperry merged 1 commit intomainfrom Jan 7, 2026
Merged
Fix AnimatePresence exit animations with Radix UI asChild#3460mattgperry merged 1 commit intomainfrom
mattgperry merged 1 commit intomainfrom
Conversation
When using Radix UI's asChild prop with motion components inside AnimatePresence, exit animations were not running. This was because externalRef was in the useMotionRef useCallback dependency array, causing the callback to be recreated whenever Radix created a new composed ref on render. The fix stores externalRef in a ref (updated via useInsertionEffect for concurrent mode safety) to access the current value without including it in the dependency array. This preserves: - React 19 cleanup function support - Proper ref forwarding - AnimatePresence exit animations with libraries like Radix UI Added E2E tests with @radix-ui/react-dialog to verify the fix. Fixes #3455 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.
Summary
asChildprop with motion componentsexternalRefin a ref (updated viauseInsertionEffectfor concurrent mode safety) instead of including it inuseCallbackdependency arrayProblem
When using Radix UI Dialog (or similar libraries) with
asChildand motion components insideAnimatePresence, exit animations were not running. The elements were immediately removed from the DOM instead of animating out.Root Cause
In
use-motion-ref.ts,externalRefwas in theuseCallbackdependency array. Radix UI'sasChildcreates a new composed callback ref on each render. This caused:useCallbackto return a new function each rendernull(unmount) then the new instance (remount)Solution
Store
externalRefin a ref (externalRefContainer) and update it viauseInsertionEffect(for concurrent mode safety). Access the current value inside the callback rather than including it in dependencies. This maintains:Test plan
@radix-ui/react-dialogreproducing the exact issue from [BUG] - Possible AnimatePresence regression in 12.24.4 #3455Fixes #3455
🤖 Generated with Claude Code