Skip to content

Commit 1f9667e

Browse files
zeyapfacebook-github-bot
authored andcommitted
Make sure props default value is restored when disconnected from animated (#53043)
Summary: Pull Request resolved: #53043 ## Changelog: [Internal] [Changed] - Make sure props default value is restored when disconnected from animated Reviewed By: sammy-SC Differential Revision: D79566216 fbshipit-source-id: b23b10101dfac5027cd6d0f0926f6e41b39715ba
1 parent a0f93ea commit 1f9667e

2 files changed

Lines changed: 101 additions & 3 deletions

File tree

packages/react-native/Libraries/Animated/__tests__/Animated-itest.js

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import type {HostInstance} from 'react-native';
1515

1616
import ensureInstance from '../../../src/private/__tests__/utilities/ensureInstance';
1717
import * as Fantom from '@react-native/fantom';
18-
import {createRef} from 'react';
18+
import {createRef, useMemo} from 'react';
1919
import {Animated, View, useAnimatedValue} from 'react-native';
2020
import {allowStyleProp} from 'react-native/Libraries/Animated/NativeAnimatedAllowlist';
2121
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
@@ -747,3 +747,98 @@ test('Animated.sequence', () => {
747747

748748
expect(_isSequenceFinished).toBe(true);
749749
});
750+
751+
test('Props default value is restored when disconnected from animated', () => {
752+
let _animatedOpacity;
753+
const elementRef = createRef<HostInstance>();
754+
755+
function MyApp({
756+
shouldAnimate,
757+
}: $ReadOnly<{
758+
shouldAnimate?: boolean,
759+
}>) {
760+
const animatedOpacity = useAnimatedValue(1, {useNativeDriver: true});
761+
762+
const opacity = useMemo(
763+
() => (shouldAnimate === true ? animatedOpacity : undefined),
764+
[shouldAnimate, animatedOpacity],
765+
);
766+
const scale = useMemo(
767+
() =>
768+
opacity?.interpolate({
769+
inputRange: [0, 1],
770+
outputRange: [0.95, 1],
771+
}) ?? new Animated.Value(1),
772+
[opacity],
773+
);
774+
_animatedOpacity = animatedOpacity;
775+
776+
return (
777+
<Animated.View
778+
ref={elementRef}
779+
style={[
780+
{
781+
opacity,
782+
transform: [{scale}],
783+
height: 100,
784+
width: 100,
785+
},
786+
]}
787+
/>
788+
);
789+
}
790+
791+
const root = Fantom.createRoot();
792+
793+
Fantom.runTask(() => {
794+
root.render(<MyApp shouldAnimate={true} />);
795+
});
796+
797+
const element = ensureInstance(elementRef.current, ReactNativeElement);
798+
799+
expect(root.getRenderedOutput({props: ['opacity']}).toJSX()).toEqual(
800+
<rn-view />, // default opacity is 1
801+
);
802+
803+
Fantom.runTask(() => {
804+
Animated.timing(_animatedOpacity, {
805+
toValue: 0,
806+
duration: 500,
807+
useNativeDriver: true,
808+
}).start();
809+
});
810+
811+
Fantom.unstable_produceFramesForDuration(500);
812+
813+
Fantom.runWorkLoop();
814+
815+
expect(Fantom.unstable_getDirectManipulationProps(element)).toEqual({
816+
opacity: 0,
817+
transform: [{scale: 0.95}],
818+
});
819+
820+
expect(
821+
root.getRenderedOutput({props: ['opacity', 'transform']}).toJSX(),
822+
).toEqual(<rn-view opacity="0" transform='[{"scale": 0.950000}]' />);
823+
824+
Fantom.runTask(() => {
825+
root.render(<MyApp shouldAnimate={false} />);
826+
});
827+
828+
expect(Fantom.unstable_getDirectManipulationProps(element)).toEqual({
829+
opacity: null,
830+
transform: null,
831+
});
832+
833+
if (ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
834+
expect(
835+
root.getRenderedOutput({props: ['opacity', 'transform']}).toJSX(),
836+
).toEqual(<rn-view transform='[{"scale": 0.950000}]' />); // TODO: T223344928 scale should be 1
837+
} else {
838+
expect(
839+
root.getRenderedOutput({props: ['opacity', 'transform']}).toJSX(),
840+
).toEqual(<rn-view transform='[{"scale": 1.000000}]' />);
841+
}
842+
843+
Fantom.runWorkLoop();
844+
});

packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/PropsAnimatedNode.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,11 @@ void PropsAnimatedNode::disconnectFromView(Tag viewTag) {
6969
void PropsAnimatedNode::restoreDefaultValues() {
7070
// If node is already disconnected from View, we cannot restore default values
7171
if (connectedViewTag_ != animated::undefinedAnimatedNodeIdentifier) {
72-
manager_->schedulePropsCommit(
73-
connectedViewTag_, folly::dynamic::object(), false, false);
72+
std::lock_guard<std::mutex> lock(propsMutex_);
73+
for (auto& iter : props_.items()) {
74+
iter.second = folly::dynamic(nullptr);
75+
}
76+
manager_->schedulePropsCommit(connectedViewTag_, props_, false, false);
7477
}
7578
}
7679

0 commit comments

Comments
 (0)