Commit eba0bfb
Enable
Summary:
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
https://github.com/user-attachments/assets/64882c09-1580-4209-a4aa-aa62bcf58287
With the current default, flickering is visible during the animation.
## To-be
https://github.com/user-attachments/assets/fa929562-36b3-4930-98b5-754098e571e3
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.
Pull Request resolved: #56652
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
Reviewed By: javache, sammy-SC
Differential Revision: D103070058
Pulled By: zeyap
fbshipit-source-id: c5f140ee28ec090677b0cc1b1ad9db35c79aba8doverrideBySynchronousMountPropsAtMountingAndroid by default on Android (#56652)1 parent 6ec4597 commit eba0bfb
4 files changed
Lines changed: 7 additions & 7 deletions
File tree
- packages/react-native
- ReactAndroid/src/main/java/com/facebook/react/internal/featureflags
- ReactCommon/react/featureflags
- scripts/featureflags
- src/private/featureflags
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
153 | 153 | | |
154 | 154 | | |
155 | 155 | | |
156 | | - | |
| 156 | + | |
157 | 157 | | |
158 | 158 | | |
159 | 159 | | |
| |||
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
288 | 288 | | |
289 | 289 | | |
290 | 290 | | |
291 | | - | |
| 291 | + | |
292 | 292 | | |
293 | 293 | | |
294 | 294 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
743 | 743 | | |
744 | 744 | | |
745 | 745 | | |
746 | | - | |
| 746 | + | |
747 | 747 | | |
748 | 748 | | |
749 | 749 | | |
| |||
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
468 | 468 | | |
469 | 469 | | |
470 | 470 | | |
471 | | - | |
| 471 | + | |
472 | 472 | | |
473 | 473 | | |
474 | 474 | | |
| |||
0 commit comments