Skip to content

Fix native animated mount flash#57391

Open
GrahamCampbell wants to merge 3 commits into
react:mainfrom
GrahamCampbell:native-animated-mount-flash
Open

Fix native animated mount flash#57391
GrahamCampbell wants to merge 3 commits into
react:mainfrom
GrahamCampbell:native-animated-mount-flash

Conversation

@GrahamCampbell

Copy link
Copy Markdown

Summary:

The C++ native animated backend (cxxNativeAnimatedEnabled) prevents the useNativeDriver first-frame flash by having AnimatedMountingOverrideDelegate re-merge a view's live animated props (getManagedProps) onto mount Update mutations, so a stale JS re-render can't reach the screen. There is a residual at connect time: connectAnimatedNodeToView registers the view (the override starts overriding it) but never runs the props node, so getManagedProps() returns an empty object until the next animation frame. If a Fabric mount transaction is pulled in that window the override has nothing to merge and the un-driven default value flashes for one frame, most visibly when a brand-new view is connected to an already mid-flight shared Animated.Value.

This seeds the props node with node->update() at the end of connectAnimatedNodeToView so getManagedProps() is live the instant the view becomes managed. No manager mutex is held at that point and update() takes only the node-local props mutex, so it is lock-safe; it is idempotent with the per-frame update and adds no extra Fabric commit because it only stages. It closes the connect-while-Update-in-flight case and mitigates the brand-new-view (Insert) first-paint case; the override only rewrites Update/Delete mutations today, so fully closing Insert is a follow-up. It also adds the missing unit coverage for the getManagedProps / hasManagedProps seam the override depends on.

Changelog:

[INTERNAL] [FIXED] - Seed managed props when a view connects to the native animated backend so they are live before the first frame, shrinking the useNativeDriver mount flash

Test Plan:

Adds ManagedPropsMountingOverrideTests.cpp to the ReactCommon animated unit tests. getManagedPropsReflectsLiveValueAcrossFrames, getManagedPropsNullForUnconnectedView, hasManagedPropsTracksConnectAndDisconnect and getManagedPropsIsolatedPerView pin the seam and pass regardless of the change. getManagedPropsLiveImmediatelyOnConnect and getManagedPropsLiveOnConnectWhileValueMidFlight are the regression cases: they fail without the seed (empty props at connect) and pass with it. Run via the animated C++ unit test target. On-device verification (iOS and Android with cxxNativeAnimatedEnabled on, frame-stepped capture of a popover/menu open) is still recommended for the user-visible flash.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 30, 2026
@GrahamCampbell GrahamCampbell changed the title Native animated mount flash Jun 30, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Jun 30, 2026
}
updatedNodeTags_.insert(node->tag());
// Seed props_ so getManagedProps() is live the instant the view is managed.
node->update();

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.

Suggested change
node->update();
node->update(/*forceFabricCommit*/ true);
@zeyap

zeyap commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

@GrahamCampbell thanks for the PR, do you have a playground repro for this issue? In fact Props node->update() will trigger a commit to the native view, so I'm a bit concerned of the side effects of doing this

@GrahamCampbell

Copy link
Copy Markdown
Author

Thanks for the review. update only stages props (map writes). The actual view push is in commitProps, which it never reaches. connectAnimatedNodeToView already dirties the node, so the commit happens that frame regardless. To make that structural, I pushed a follow-up that seeds via a collect-only collectProps with no schedulePropsCommit.

@GrahamCampbell

GrahamCampbell commented Jun 30, 2026

Copy link
Copy Markdown
Author
@meta-codesync

meta-codesync Bot commented Jul 1, 2026

Copy link
Copy Markdown

@zeyap has imported this pull request. If you are a Meta employee, you can view this in D110323404.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

2 participants