Skip to content

Commit

Permalink
Speed up animation on back button press + animated reattach on tab sw…
Browse files Browse the repository at this point in the history
…itch (#46438)

Summary:
Pull Request resolved: #46438

When hiding a view with React.Activity, React will "detach" all the views in teh subtree (call all their effect cleanups) and then upon showing it again will attach them (call all their effects again).

This was previously causing problems with useAnimatedProps and #46205 was intended to fix it (cc javache), but it's still a perf drain to have to detach all of this and then re-attach it upon show. Worse, it makes it so that we can't actually do any animations upon re-showing a view until all the passive effects have run to re-attach the views to the animations.

So instead, what this diff does is lean on the fact that useInsertionEffect *does not* clean up and rerun when Activity goes from hidden to visible and vice versa. Thus, we can rely on it to only detach the animated node when we're *actually* unmounting - rather than when we're simply hiding/showing.

Changelog:
[General][Changed] - Improved the performance of unmounting (and updating, when an enclosing Activity becomes hidden) Animated components

Reviewed By: yungsters, sammy-SC

Differential Revision: D62398039

fbshipit-source-id: af286e428188b5104f6cfd3fd4d8c9f791dedb8d
  • Loading branch information
Royi Hagigi authored and facebook-github-bot committed Sep 11, 2024
1 parent 65d8f66 commit 46abda5
Showing 1 changed file with 27 additions and 24 deletions.
51 changes: 27 additions & 24 deletions packages/react-native/Libraries/Animated/useAnimatedProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import AnimatedValue from './nodes/AnimatedValue';
import {
useCallback,
useEffect,
useInsertionEffect,
useLayoutEffect,
useMemo,
useReducer,
Expand Down Expand Up @@ -314,8 +315,8 @@ function useAnimatedPropsLifecycle_layoutEffects(node: AnimatedProps): void {
* NOTE: unlike `useAnimatedPropsLifecycle_layoutEffects`, this version uses passive effects to setup animation graph.
*/
function useAnimatedPropsLifecycle_passiveEffects(node: AnimatedProps): void {
const prevNodeRef = useRef<?AnimatedProps>(null);
const isUnmountingRef = useRef<boolean>(false);
const attachedNodeRef =
useRef<?{node: AnimatedProps, listener: ?EventSubscription}>(null);

useEffect(() => {
// It is ok for multiple components to call `flushQueue` because it noops
Expand All @@ -324,43 +325,45 @@ function useAnimatedPropsLifecycle_passiveEffects(node: AnimatedProps): void {
NativeAnimatedHelper.API.flushQueue();
});

useEffect(() => {
isUnmountingRef.current = false;
useInsertionEffect(() => {
return () => {
isUnmountingRef.current = true;
const attachedNode = attachedNodeRef.current;
if (attachedNode != null) {
const {node: prevNode, listener} = attachedNode;
// NOTE: Do not restore default values on unmount, see D18197735.
prevNode.__detach();
listener?.remove();
attachedNodeRef.current = null;
}
};
}, []);

useEffect(() => {
node.__attach();
let drivenAnimationEndedListener: ?EventSubscription = null;

if (node.__isNative) {
drivenAnimationEndedListener =
NativeAnimatedHelper.nativeEventEmitter.addListener(
let prevAttachedNode = null;
if (attachedNodeRef.current !== node) {
node.__attach();
prevAttachedNode = attachedNodeRef.current;
let listener: ?EventSubscription = null;

if (node.__isNative) {
listener = NativeAnimatedHelper.nativeEventEmitter.addListener(
'onUserDrivenAnimationEnded',
data => {
node.update();
},
);
}

attachedNodeRef.current = {node, listener};
}
if (prevNodeRef.current != null) {
const prevNode = prevNodeRef.current;

if (prevAttachedNode != null) {
const {node: prevNode, listener} = prevAttachedNode;
// TODO: Stop restoring default values (unless `reset` is called).
prevNode.__restoreDefaultValues();
prevNode.__detach();
prevNodeRef.current = null;
listener?.remove();
}
return () => {
if (isUnmountingRef.current) {
// NOTE: Do not restore default values on unmount, see D18197735.
node.__detach();
} else {
prevNodeRef.current = node;
}

drivenAnimationEndedListener?.remove();
};
}, [node]);
}

Expand Down

0 comments on commit 46abda5

Please sign in to comment.