Skip to content

Commit 5680b38

Browse files
genkikondofacebook-github-bot
authored andcommitted
When animating using native driver, trigger rerender on animation completion
Summary: 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. 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). 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 Differential Revision: D46574511 fbshipit-source-id: 2d011dfc360a4f72a659573f8e33bfcbbf99117d
1 parent 92b3fa4 commit 5680b38

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

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

Lines changed: 24 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,13 @@ 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+
const animatedPropsNode = this.__findAnimatedPropsNode(animatedValue);
113+
if (animatedPropsNode != null) {
114+
animatedPropsNode.update();
115+
}
92116
},
93117
);
94118
} 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)