RN: Ship scheduleAnimatedCleanupInMicrotask (#50341)

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

Ships tge `scheduleAnimatedCleanupInMicrotask` feature flag, which changes the cleanup of `AnimatedProps` to occur in a microtask instead of synchronously during effect cleanup (for unmount) or subsequent mounts (for updates).

Changelog:
[General][Changed] - When an `Animated` component is unmounted, any completion callbacks will now be called in a microtask instead of during the commit phase.

Reviewed By: javache

Differential Revision: D71942778

fbshipit-source-id: cbe636d5cff84dfeca2f21ead374609c536e91ad
This commit is contained in:
Tim Yung
2025-03-28 08:13:39 -07:00
committed by Facebook GitHub Bot
parent e704f8ac2f
commit da1bf8d1d1
3 changed files with 12 additions and 10 deletions
@@ -582,13 +582,12 @@ const definitions: FeatureFlagDefinitions = {
ossReleaseStage: 'none',
},
scheduleAnimatedCleanupInMicrotask: {
defaultValue: false,
defaultValue: true,
metadata: {
dateAdded: '2025-01-22',
description:
'Changes the cleanup of`AnimatedProps` to occur in a microtask instead of synchronously during effect cleanup (for unmount) or subsequent mounts (for updates).',
'Changes the cleanup of `AnimatedProps` to occur in a microtask instead of synchronously during effect cleanup (for unmount) or subsequent mounts (for updates).',
expectedReleaseValue: true,
purpose: 'experimentation',
purpose: 'release',
},
ossReleaseStage: 'none',
},
@@ -151,7 +151,7 @@ describe('Native Animated', () => {
const tag = opacity.__getNativeTag();
await unmount(root);
jest.runAllTicks();
expect(NativeAnimatedModule.getValue).toBeCalledWith(
tag,
expect.any(Function),
@@ -175,7 +175,7 @@ describe('Native Animated', () => {
const tag = opacity.__getNativeTag();
await unmount(root);
jest.runAllTicks();
expect(NativeAnimatedModule.getValue).toBeCalledWith(
tag,
expect.any(Function),
@@ -404,7 +404,7 @@ describe('Native Animated', () => {
expect(NativeAnimatedModule.dropAnimatedNode).not.toHaveBeenCalled();
await unmount(root);
jest.runAllTicks();
expect(
NativeAnimatedModule.disconnectAnimatedNodes,
).toHaveBeenCalledTimes(2);
@@ -1387,11 +1387,13 @@ describe('Native Animated', () => {
expect(NativeAnimatedModule.restoreDefaultValues).not.toHaveBeenCalled();
await update(root, <Animated.View style={{opacity: opacityB}} />);
jest.runAllTicks();
expect(NativeAnimatedModule.restoreDefaultValues).toHaveBeenCalledTimes(
1,
);
await unmount(root);
jest.runAllTicks();
// Make sure it doesn't get called on unmount.
expect(NativeAnimatedModule.restoreDefaultValues).toHaveBeenCalledTimes(
1,
@@ -1416,6 +1418,7 @@ describe('Native Animated', () => {
);
await unmount(root);
jest.runAllTicks();
expect(
NativeAnimatedModule.disconnectAnimatedNodeFromView,
).toBeCalledWith(propsTag, 1);
@@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<d1971c39b882dcf8872ecc0bd91594c8>>
* @generated SignedSource<<b4da778c80a82ff5c93c7d799ff0c580>>
* @flow strict
*/
@@ -137,9 +137,9 @@ export const fixVirtualizeListCollapseWindowSize: Getter<boolean> = createJavaSc
export const isLayoutAnimationEnabled: Getter<boolean> = createJavaScriptFlagGetter('isLayoutAnimationEnabled', true);
/**
* Changes the cleanup of`AnimatedProps` to occur in a microtask instead of synchronously during effect cleanup (for unmount) or subsequent mounts (for updates).
* Changes the cleanup of `AnimatedProps` to occur in a microtask instead of synchronously during effect cleanup (for unmount) or subsequent mounts (for updates).
*/
export const scheduleAnimatedCleanupInMicrotask: Getter<boolean> = createJavaScriptFlagGetter('scheduleAnimatedCleanupInMicrotask', false);
export const scheduleAnimatedCleanupInMicrotask: Getter<boolean> = createJavaScriptFlagGetter('scheduleAnimatedCleanupInMicrotask', true);
/**
* Enables use of AnimatedObject for animating transform values.