Commit ee6958a
Sync JS-side AnimatedValue before invoking native-driver completion callback (#57021)
Summary:
Pull Request resolved: #57021
`Animation.__startAnimationIfNative` invoked the user's `start({finished})`
callback BEFORE syncing the JS-side `AnimatedValue` with the post-animation
value reported by the native side. Any caller that read the `AnimatedValue`
from inside the callback, or from a React re-render that the callback
triggered, observed the **pre-animation** value, producing visual jumps.
Concrete impact: an `<Animated.View>` whose `transform: [{scaleX}]` is
driven by `value.interpolate({inputRange: [0, 1], outputRange: [0.5, 1]})`
would render at `scaleX = interp(0) = 0.5` after the animation finished,
instead of at `scaleX = interp(1) = 1`. The same pattern affects opacity,
color and any other style derived from an animated value read during a
re-render scheduled by the completion callback.
This change reorders the native completion callback so
`animatedValue.__onAnimatedValueUpdateReceived(value, offset)` runs BEFORE
`this.__notifyAnimationEnd(result)`. The user's callback (and any re-render
it schedules) now observes the post-animation JS value.
The reorder is gated behind a new JS-only feature flag,
`animatedShouldSyncValueBeforeStartCallback`, which defaults to `true`
(the fix is on by default). Set the flag to `false` to opt out and
restore the pre-fix ordering as a kill-switch.
A Fantom integration test in `Animated-itest.js` exercises the exact
scenario: starts a `useNativeDriver: true` `Animated.timing(0 -> 1)`,
captures both `_value._value` and `value.interpolate(...).__getValue()`
inside the `start({finished})` callback and asserts the value matches the
flag state (pre-animation when off, post-animation when on).
## Behavior change to consider
The reorder also changes the order in which JS-side observers of the
`AnimatedValue` are notified relative to the `start({finished})` callback.
This was confirmed empirically against the current and the proposed
ordering.
Before (flag off):
1. `start({finished})` callback fires
2. `AnimatedValue.addListener(...)` subscribers receive the post-animation value
After (flag on):
1. `AnimatedValue.addListener(...)` subscribers receive the post-animation value
2. `start({finished})` callback fires
For the vast majority of callers this is irrelevant or strictly better
(observers and callback now agree on the same value). The flag defaults
to `true` so the fix ships immediately; the flag itself stays as a
kill-switch in case real-world callers turn out to depend on the
previous ordering. Once adoption has been verified the flag can be
removed entirely.
Changelog:
[General][Fixed] - Sync JS-side `Animated.Value` with the post-animation value before invoking `Animated.timing(...).start({finished})` callbacks so reads from inside the callback (or from React re-renders it triggers) observe the post-animation value rather than the pre-animation value. Gated behind a new JS-only feature flag, `animatedShouldSyncValueBeforeStartCallback`, defaulting to `true` (set to `false` to opt out).
Reviewed By: javache, zeyap
Differential Revision: D106940382
fbshipit-source-id: c6f27956030d2a9c4016a30e2dff8d9424ad7b331 parent a18f53d commit ee6958a
4 files changed
Lines changed: 103 additions & 7 deletions
File tree
- packages/react-native
- Libraries/Animated
- __tests__
- animations
- scripts/featureflags
- src/private/featureflags
Lines changed: 72 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
735 | 735 | | |
736 | 736 | | |
737 | 737 | | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
Lines changed: 13 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
141 | 141 | | |
142 | 142 | | |
143 | 143 | | |
144 | | - | |
145 | | - | |
146 | 144 | | |
147 | 145 | | |
148 | 146 | | |
149 | 147 | | |
150 | | - | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
151 | 151 | | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
152 | 160 | | |
153 | 161 | | |
154 | 162 | | |
| |||
158 | 166 | | |
159 | 167 | | |
160 | 168 | | |
161 | | - | |
162 | | - | |
| 169 | + | |
| 170 | + | |
163 | 171 | | |
164 | 172 | | |
165 | 173 | | |
| |||
Lines changed: 11 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
992 | 992 | | |
993 | 993 | | |
994 | 994 | | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
995 | 1006 | | |
996 | 1007 | | |
997 | 1008 | | |
| |||
Lines changed: 7 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
145 | 146 | | |
146 | 147 | | |
147 | 148 | | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
148 | 154 | | |
149 | 155 | | |
150 | 156 | | |
| |||
0 commit comments