Skip to content

Enable overrideBySynchronousMountPropsAtMountingAndroid by default on Android#56652

Closed
jingjing2222 wants to merge 1 commit intofacebook:mainfrom
jingjing2222:fix-android-flickering
Closed

Enable overrideBySynchronousMountPropsAtMountingAndroid by default on Android#56652
jingjing2222 wants to merge 1 commit intofacebook:mainfrom
jingjing2222:fix-android-flickering

Conversation

@jingjing2222
Copy link
Copy Markdown
Contributor

@jingjing2222 jingjing2222 commented Apr 29, 2026

Enable overrideBySynchronousMountPropsAtMountingAndroid by default on Android.

This flag was added to prevent regular Fabric mount updates from overriding newer props that were already applied synchronously by Native Animated direct manipulation. Without this path enabled, Android can still hit a race where:

  1. Native Animated applies transform props synchronously on the UI thread.
  2. A regular Fabric mount update for the same view is already in flight with older props.
  3. That regular mount update reaches SurfaceMountingManager.updateProps() later and overwrites the newer synchronous animated value.
  4. The view visibly jumps/flickers during the animation.

This is not just theoretical. I spent about a week debugging this from a real Android flickering issue, and the final repro is intentionally very small. The visual impact is clear in the README videos, and I am attaching the same videos here as well.

Minimal repro:
https://github.com/jingjing2222/fix-react-native-android-flickering

The repro uses React Native 0.85.2 with Android Fabric. The JS only runs Animated.timing(..., {useNativeDriver: true}) for translateX and translateY.

As-is

as-is.mov

With the current default, flickering is visible during the animation.

To-be

to-be.mov

With overrideBySynchronousMountPropsAtMountingAndroid enabled, the flickering is gone.

The existing mounting-layer flag fixes this by storing the latest synchronous mount props and reapplying them when regular mount props are processed. This makes the final mounted props preserve the latest Native Animated direct manipulation value.

Because this can happen with a simple native-driver transform animation, enabling this default should prevent other Android users from spending time debugging the same race condition.

Why Android only?

iOS Fabric already tracks props managed by NativeAnimated on the component view. When NativeAnimated synchronously updates props such as transform or opacity, iOS records those prop keys and prevents later normal Fabric updates from re-applying stale values for those props.

Android Fabric has a similar mechanism through tagToSynchronousMountProps, but it was gated behind overrideBySynchronousMountPropsAtMountingAndroid, which defaults to false. Therefore, NativeAnimated could synchronously apply the final transform to the view, and a later normal Fabric props update could re-apply stale transform props, causing a transient flicker.

This change makes Android preserve synchronously mounted NativeAnimated props across later Fabric prop updates, matching the ownership behavior already present on iOS.

Changelog:

[ANDROID] [FIXED] - Prevent stale Fabric mount updates from overriding newer Native Animated synchronous prop updates.

Test Plan:

  • Ran yarn featureflags --update
  • Ran git diff --check
  • Verified generated feature flag defaults were updated for Android, C++, and JS.
  • Verified the minimal repro with the README videos attached above:
    • as-is/current default: flickering is visible during translateX/translateY native-driver animation
    • to-be/flag enabled: flickering is not visible

@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 Apr 29, 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 Apr 29, 2026
@jingjing2222 jingjing2222 changed the title Enable overrideBySynchronousMountPropsAtMountingAndroid by default on Android. Enable overrideBySynchronousMountPropsAtMountingAndroid by default on Android Apr 29, 2026
@cortinico
Copy link
Copy Markdown
Contributor

cc @zeyap

@jingjing2222
Copy link
Copy Markdown
Contributor Author

@jingjing2222
Copy link
Copy Markdown
Contributor Author

jingjing2222 commented Apr 29, 2026

rerun Test All / test_ios_rntester (Release, false) (pull_request) please 🙏

Test All / test_ios_rntester (Release, false) (pull_request) too please 🙏

@zeyap
Copy link
Copy Markdown
Contributor

zeyap commented Apr 29, 2026

Yes from previous experiments this flag was pretty low risk, glad it fixed your problem🫡

@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented Apr 29, 2026

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

@meta-codesync meta-codesync Bot closed this in eba0bfb Apr 30, 2026
@facebook-github-tools facebook-github-tools Bot added the Merged This PR has been merged. label Apr 30, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented Apr 30, 2026

@zeyap merged this pull request in eba0bfb.

@react-native-bot
Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @jingjing2222 in eba0bfb

When will my fix make it into a release? | How to file a pick request?

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. Merged This PR has been merged. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants