Reset animatedView when detaching AnimatedProps (#46205)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46205

When React.Activity unmounts and remounts effects, we fail to re-attach the native view to the NativeAnimated nodes, which causes animations to stop working.

Changelog: [Internal]

Reviewed By: sammy-SC, bvanderhoof

Differential Revision: D61662164

fbshipit-source-id: 8e86502f7258beba02d5e60b31864974d7288af5
This commit is contained in:
Pieter De Baets
2024-08-26 09:38:00 -07:00
committed by Facebook GitHub Bot
parent b6fc75a121
commit fdb77ae924
2 changed files with 56 additions and 1 deletions
@@ -25,6 +25,7 @@ jest
import {format} from 'node:util';
import * as React from 'react';
import {createRef} from 'react';
const {create, unmount, update} = require('../../../jest/renderer');
const Animated = require('../Animated').default;
@@ -1265,7 +1266,7 @@ describe('Native Animated', () => {
});
describe('Animated Components', () => {
it('Should restore default values on prop updates only', async () => {
it('should restore default values on prop updates only', async () => {
const opacity = new Animated.Value(0);
opacity.__makeNative();
@@ -1283,5 +1284,57 @@ describe('Native Animated', () => {
1,
);
});
it('connects the native view on mount and disconnects on unmount', async () => {
const opacity = new Animated.Value(0, {useNativeDriver: true});
const root = await create(<Animated.View style={{opacity}} />);
// AnimatedProps > AnimatedStyle > opacity AnimatedValue
const propsTag = opacity
.__getChildren()[0]
.__getChildren()[0]
.__getNativeTag();
expect(NativeAnimatedModule.connectAnimatedNodeToView).toBeCalledWith(
propsTag,
1,
);
await unmount(root);
expect(
NativeAnimatedModule.disconnectAnimatedNodeFromView,
).toBeCalledWith(propsTag, 1);
});
it('reconnects the native view when the component is remounted', async () => {
const opacity = new Animated.Value(0, {useNativeDriver: true});
const ref = createRef();
await create(<Animated.View ref={ref} style={{opacity}} />);
// AnimatedProps > AnimatedStyle > opacity AnimatedValue
const propsNode = opacity.__getChildren()[0].__getChildren()[0];
let propsTag = propsNode.__nativeTag;
expect(NativeAnimatedModule.connectAnimatedNodeToView).nthCalledWith(
1,
propsTag,
1,
);
// Simulate what happens when React.Activity unmounts and remounts
propsNode.__detach();
expect(
NativeAnimatedModule.disconnectAnimatedNodeFromView,
).toBeCalledWith(propsTag, 1);
propsNode.__attach();
propsNode.setNativeView(ref.current);
propsTag = propsNode.__nativeTag;
expect(NativeAnimatedModule.connectAnimatedNodeToView).nthCalledWith(
2,
propsTag,
1,
);
});
});
});
@@ -88,6 +88,8 @@ export default class AnimatedProps extends AnimatedNode {
if (this.__isNative && this._animatedView) {
this.__disconnectAnimatedView();
}
this._animatedView = null;
for (const key in this._props) {
const value = this._props[key];
if (value instanceof AnimatedNode) {