Skip to content

fix(Reanimated): preserve layout updates during entering animations - #10382

Closed
ngocdevv wants to merge 7 commits into
software-mansion:mainfrom
ngocdevv:fix/entering-animation-layout-updates
Closed

fix(Reanimated): preserve layout updates during entering animations#10382
ngocdevv wants to merge 7 commits into
software-mansion:mainfrom
ngocdevv:fix/entering-animation-layout-updates

Conversation

@ngocdevv

@ngocdevv ngocdevv commented Aug 22, 2026

Copy link
Copy Markdown

Note

This pull request was authored by AI on behalf of @ngocdevv.

Summary

Fixes #10161.

React updates that do not have a configured layout transition are passed directly to the mounting layer. When such an update happens during an entering animation, the animation proxy kept the original finalView. The next animation frame was then based on that stale snapshot and reapplied the old layout metrics, leaving the native hit-testing bounds smaller than the visible content.

This change keeps the ongoing animation target synchronized with pass-through React updates in both the legacy and experimental Layout Animations proxies. The experimental proxy uses the LightNode's merged current view so Android diffed props are preserved as well.

Test plan

Manual regression test using the reproduction from https://github.com/mozzius/layout-animation-grow-repro:

  1. Build and run the Fabric example app on Android.
  2. Render the reproduction in EmptyExample.
  3. Wait until the panel grows from 80 to 130 points during SlideInRight.
  4. Tap the bottom of the green target, below the panel's original bottom edge.
  5. Verify that the press counter increments.
  6. Repeat with USE_ANIMATION_BACKEND disabled and enabled.

Validated on a Pixel 9 Pro Android API 36 emulator with both Layout Animations backends. In each case, a tap in the previously stale lower region incremented the counter from 0 to 1.

Checks run:

  • yarn build-packages
  • yarn workspace react-native-reanimated format:common --dry-run -Werror
  • yarn workspace react-native-reanimated lint:apple
  • yarn workspace react-native-reanimated lint:js
  • yarn workspace react-native-reanimated type:check:src:native
  • yarn workspace react-native-reanimated test --runInBand (1,556 tests)
  • ./gradlew :app:assembleDebug -PreactNativeArchitectures=arm64-v8a --no-daemon with both Layout Animations backends

Changelog

  • I added an entry to the Unpublished section of each changed package's CHANGELOG.md, or this PR does not change react-native-reanimated or react-native-worklets.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cf609fd3-38d1-4f5b-b961-079949c92b04

📥 Commits

Reviewing files that changed from the base of the PR and between 51cac22 and 79a9d24.

📒 Files selected for processing (1)
  • packages/react-native-reanimated/CHANGELOG.md

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Updated legacy and experimental layout animation proxies to refresh ongoing animation targets from current ShadowView values. Revised experimental mutation handling to defer exiting animations, preserve animated subtrees, translate host indices, and flush dead nodes after light-tree updates. Added a changelog entry for stale entering-animation frames.

Merge Risk: 🟡 Moderate · up to 79a9d

The experimental layout-animation proxy can abort debug builds when deleting animated nodes and leak node entries in release builds because its deletion assertion conflicts with the animation lifecycle. This concrete runtime issue should be fixed before merging.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The proxy changes are in scope for #10161, but the changelog also documents breaking changes to animated refs and unmounted-ref measurement behavior that are not part of the linked issue or stated imp… Remove the unrelated breaking-change changelog entries, or provide linked issue requirements and implementation evidence that justify them in this pull request.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: preserving layout updates during entering animations.
Description check ✅ Passed The description directly explains the stale layout target issue, the legacy and experimental proxy fixes, and the validation performed.
Linked Issues check ✅ Passed The implementation addresses issue #10161 by synchronizing ongoing animation targets with pass-through layout updates in both layout animation proxies, which preserves hit-testing geometry for visibly…
Full details: Linked Issues check

Explanation

The implementation addresses issue #10161 by synchronizing ongoing animation targets with pass-through layout updates in both layout animation proxies, which preserves hit-testing geometry for visibly expanded content.

Full details: Out of Scope Changes check

Explanation

The proxy changes are in scope for #10161, but the changelog also documents breaking changes to animated refs and unmounted-ref measurement behavior that are not part of the linked issue or stated implementation objective.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ngocdevv

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

CodeRabbit chat interactions are restricted to organization members for this repository. Ask an organization member to interact with CodeRabbit, or set chat.allow_non_org_members: true in your configuration.

…ion-layout-updates

# Conflicts:
#	packages/react-native-reanimated/CHANGELOG.md
@pawicao pawicao self-assigned this Aug 24, 2026
…ion-layout-updates

# Conflicts:
#	packages/react-native-reanimated/CHANGELOG.md
…ion-layout-updates

# Conflicts:
#	packages/react-native-reanimated/CHANGELOG.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp (1)

271-281: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Accept DELETED in the Delete case and erase the stale lightNodes_ entry.

Bruce found the real smoking gun here. startAnimationsRecursively marks removed descendants as DELETED and emits Remove followed by Delete, but it does not erase their lightNodes_ entries. The current Delete case rejects DELETED in debug builds and retains the entry in release builds.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ffafc504-55ea-4d9b-83ee-cb94732fe60a

📥 Commits

Reviewing files that changed from the base of the PR and between 1cd8697 and 3299d2b.

📒 Files selected for processing (3)
  • packages/react-native-reanimated/CHANGELOG.md
  • packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp
  • packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/react-native-reanimated/CHANGELOG.md

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.

@ngocdevv

Copy link
Copy Markdown
Author

Regarding the CodeRabbit outside-diff warning: the flagged Delete logic comes from upstream #10392 and is not part of this PR's final diff. React Native emits descendant Delete mutations before the removed subtree's root Remove, as described in #10392, so each entry is erased while its state is still UNDEFINED. startAnimationsRecursively later walks retained child shared pointers and may mark a now-detached node DELETED; there is no later original Delete for that node. The final diff against main remains limited to the five files for #10161, and the merged experimental proxy passed the arm64 Android C++ build.

@pawicao

pawicao commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Thank you for this PR and the clear repro. Indeed the bug is confirmed, and your fix seems to have been addressing it well.

Note that these days we are working on some refactors of the layout animations proxy and the current rework in this matter addresses the issue as well (that refactor also caused all the conflicts that appeared in your PR afterwards). To be more specific #10373 is something we wish to land in the next release and its work includes the fix for the new refactored structure of the proxy as well.

I will therefore close this in favor of #10373 that supersedes this PR. Nevertheless, big thanks for your will of contribution. Cheers!

@pawicao pawicao closed this Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Growing view during entering animation leaves content untappable

2 participants