diff --git a/packages/react-native/Libraries/Animated/__tests__/AnimatedNative-test.js b/packages/react-native/Libraries/Animated/__tests__/AnimatedNative-test.js
index 4d2f2ce3e32..6e5c9b302b8 100644
--- a/packages/react-native/Libraries/Animated/__tests__/AnimatedNative-test.js
+++ b/packages/react-native/Libraries/Animated/__tests__/AnimatedNative-test.js
@@ -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();
+
+ // 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();
+
+ // 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,
+ );
+ });
});
});
diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js b/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js
index d6c3462590b..d8a048e82eb 100644
--- a/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js
+++ b/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js
@@ -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) {