Skip to content

Commit 03f70bf

Browse files
genkikondofacebook-github-bot
authored andcommitted
When animating using native driver, trigger rerender on animation completion (#37786)
Summary: Pull Request resolved: #37786 When using the native driver for animations that involve layout changes (ie. translateY and other transforms, but not styles such as opacity), because it bypasses Fabric, the new coordinates are not updated so the Pressability responder region/tap target is incorrect. Prior diffs ensure that upon completion of natively driven animations, the final values are synced to the JS side AnimatedValue nodes. In this diff, on completion of a natively driven animation, AnimatedProps.update() is called, which in turn calls the value update callback on AnimatedProps, which [triggers a rerender (via setState)](https://www.internalfb.com/code/fbsource/[566daad5db45807260a8af1f85385ca86aebf894]/xplat/js/react-native-github/packages/react-native/Libraries/Animated/useAnimatedProps.js?lines=80) which has the effect of pushing the latest animated values to Fabric. Alternative considered was using setNativeProps, but that approach was dropped as setNativeProps was only introduced to make migration easier and should not be used for new code, as per sammy-SC. Changelog: [General][Fixed] - When animating using native driver, trigger rerender on animation completion in order to update Pressability responder regions Reviewed By: rshest Differential Revision: D46574511 fbshipit-source-id: 185471b28f5f7e3ba9d62d2ac196e9b65b07a86e
1 parent 51cea49 commit 03f70bf

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

packages/react-native/Libraries/Animated/animations/Animation.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
'use strict';
1212

1313
import type {PlatformConfig} from '../AnimatedPlatformConfig';
14+
import type AnimatedNode from '../nodes/AnimatedNode';
1415
import type AnimatedValue from '../nodes/AnimatedValue';
1516

1617
import NativeAnimatedHelper from '../NativeAnimatedHelper';
18+
import AnimatedProps from '../nodes/AnimatedProps';
1719

1820
export type EndResult = {finished: boolean, value?: number, ...};
1921
export type EndCallback = (result: EndResult) => void;
@@ -65,6 +67,21 @@ export default class Animation {
6567
onEnd && onEnd(result);
6668
}
6769

70+
__findAnimatedPropsNode(node: AnimatedNode): ?AnimatedProps {
71+
if (node instanceof AnimatedProps) {
72+
return node;
73+
}
74+
75+
for (const child of node.__getChildren()) {
76+
const result = this.__findAnimatedPropsNode(child);
77+
if (result) {
78+
return result;
79+
}
80+
}
81+
82+
return null;
83+
}
84+
6885
__startNativeAnimation(animatedValue: AnimatedValue): void {
6986
const startNativeAnimationWaitId = `${startNativeAnimationNextId}:startAnimation`;
7087
startNativeAnimationNextId += 1;
@@ -89,6 +106,10 @@ export default class Animation {
89106
if (value != null) {
90107
animatedValue.__onAnimatedValueUpdateReceived(value);
91108
}
109+
110+
// Once the JS side node is synced with the updated values, trigger an
111+
// update on the AnimatedProps node to call any registered callbacks.
112+
this.__findAnimatedPropsNode(animatedValue)?.update();
92113
},
93114
);
94115
} catch (e) {

packages/react-native/Libraries/Animated/useAnimatedProps.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ export default function useAnimatedProps<TProps: {...}, TInstance>(
6666
// changes), but `setNativeView` already optimizes for that.
6767
node.setNativeView(instance);
6868

69-
// NOTE: This callback is only used by the JavaScript animation driver.
69+
// NOTE: When using the JS animation driver, this callback is called on
70+
// every animation frame. When using the native driver, this callback is
71+
// called when the animation completes.
7072
onUpdateRef.current = () => {
7173
if (
7274
process.env.NODE_ENV === 'test' ||

0 commit comments

Comments
 (0)