mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
fix crash when view with event driven animation is unmounted (#52807)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52807 changelog: [internal] Fixes a crash that occurs when event driven animation is attached to a view that is unmounted. Reviewed By: zeyap Differential Revision: D78889689 fbshipit-source-id: 6bc534c3d80a7ed2fc5e0ac378e58343fef45430
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0d13474161
commit
dbdf39a8fe
@@ -151,6 +151,66 @@ test('animation driven by onScroll event', () => {
|
||||
expect(viewElement.getBoundingClientRect().y).toBe(100);
|
||||
});
|
||||
|
||||
test('animation driven by onScroll event when animated view is unmounted', () => {
|
||||
const scrollViewRef = createRef<HostInstance>();
|
||||
|
||||
component PressableWithNativeDriver(mountAnimatedView: boolean) {
|
||||
const currScroll = useAnimatedValue(0);
|
||||
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
{mountAnimatedView ? (
|
||||
<Animated.View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
width: 10,
|
||||
height: 10,
|
||||
transform: [{translateY: currScroll}],
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<Animated.ScrollView
|
||||
ref={scrollViewRef}
|
||||
onScroll={Animated.event(
|
||||
[
|
||||
{
|
||||
nativeEvent: {
|
||||
contentOffset: {
|
||||
y: currScroll,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
{useNativeDriver: true},
|
||||
)}>
|
||||
<View style={{height: 1000, width: 100}} />
|
||||
</Animated.ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const root = Fantom.createRoot();
|
||||
Fantom.runTask(() => {
|
||||
root.render(<PressableWithNativeDriver mountAnimatedView={true} />);
|
||||
});
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(<PressableWithNativeDriver mountAnimatedView={false} />);
|
||||
});
|
||||
|
||||
const scrollViewelement = ensureInstance(
|
||||
scrollViewRef.current,
|
||||
ReactNativeElement,
|
||||
);
|
||||
|
||||
Fantom.scrollTo(scrollViewelement, {
|
||||
x: 0,
|
||||
y: 50,
|
||||
});
|
||||
|
||||
Fantom.runWorkLoop();
|
||||
});
|
||||
|
||||
test('animated opacity', () => {
|
||||
let _opacity;
|
||||
let _opacityAnimation;
|
||||
|
||||
+39
-35
@@ -406,47 +406,51 @@ void NativeAnimatedNodesManager::handleAnimatedEvent(
|
||||
if (!isOnRenderThread_) {
|
||||
return;
|
||||
}
|
||||
if (eventDrivers_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!eventDrivers_.empty()) {
|
||||
bool foundAtLeastOneDriver = false;
|
||||
bool foundAtLeastOneDriver = false;
|
||||
|
||||
const auto key = EventAnimationDriverKey{
|
||||
.viewTag = viewTag,
|
||||
.eventName = EventEmitter::normalizeEventType(eventName)};
|
||||
if (auto driversIter = eventDrivers_.find(key);
|
||||
driversIter != eventDrivers_.end()) {
|
||||
auto& drivers = driversIter->second;
|
||||
if (!drivers.empty()) {
|
||||
foundAtLeastOneDriver = true;
|
||||
}
|
||||
for (const auto& driver : drivers) {
|
||||
if (auto value = driver->getValueFromPayload(eventPayload)) {
|
||||
auto node =
|
||||
getAnimatedNode<ValueAnimatedNode>(driver->getAnimatedNodeTag());
|
||||
stopAnimationsForNode(node->tag());
|
||||
if (node->setRawValue(value.value())) {
|
||||
updatedNodeTags_.insert(node->tag());
|
||||
}
|
||||
const auto key = EventAnimationDriverKey{
|
||||
.viewTag = viewTag,
|
||||
.eventName = EventEmitter::normalizeEventType(eventName)};
|
||||
if (auto driversIter = eventDrivers_.find(key);
|
||||
driversIter != eventDrivers_.end()) {
|
||||
auto& drivers = driversIter->second;
|
||||
if (!drivers.empty()) {
|
||||
foundAtLeastOneDriver = true;
|
||||
}
|
||||
for (const auto& driver : drivers) {
|
||||
if (auto value = driver->getValueFromPayload(eventPayload)) {
|
||||
auto node =
|
||||
getAnimatedNode<ValueAnimatedNode>(driver->getAnimatedNodeTag());
|
||||
if (node == nullptr) {
|
||||
continue;
|
||||
}
|
||||
stopAnimationsForNode(node->tag());
|
||||
if (node->setRawValue(value.value())) {
|
||||
updatedNodeTags_.insert(node->tag());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundAtLeastOneDriver && !isEventAnimationInProgress_) {
|
||||
// There is an animation driver handling this event and
|
||||
// event driven animation has not been started yet.
|
||||
isEventAnimationInProgress_ = true;
|
||||
// Some platforms (e.g. iOS) have UI tick listener disable
|
||||
// when there are no active animations. Calling
|
||||
// `startRenderCallbackIfNeeded` will call platform specific code to
|
||||
// register UI tick listener.
|
||||
startRenderCallbackIfNeeded();
|
||||
// Calling startOnRenderCallback_ will register a UI tick listener.
|
||||
// The UI ticker listener will not be called until the next frame.
|
||||
// That's why, in case this is called from the UI thread, we need to
|
||||
// proactivelly trigger the animation loop to avoid showing stale
|
||||
// frames.
|
||||
onRender();
|
||||
}
|
||||
if (foundAtLeastOneDriver && !isEventAnimationInProgress_) {
|
||||
// There is an animation driver handling this event and
|
||||
// event driven animation has not been started yet.
|
||||
isEventAnimationInProgress_ = true;
|
||||
// Some platforms (e.g. iOS) have UI tick listener disable
|
||||
// when there are no active animations. Calling
|
||||
// `startRenderCallbackIfNeeded` will call platform specific code to
|
||||
// register UI tick listener.
|
||||
startRenderCallbackIfNeeded();
|
||||
// Calling startOnRenderCallback_ will register a UI tick listener.
|
||||
// The UI ticker listener will not be called until the next frame.
|
||||
// That's why, in case this is called from the UI thread, we need to
|
||||
// proactivelly trigger the animation loop to avoid showing stale
|
||||
// frames.
|
||||
onRender();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ class EventAnimationDriver {
|
||||
protected:
|
||||
std::vector<std::string> eventPath_;
|
||||
|
||||
Tag animatedValueTag_;
|
||||
const Tag animatedValueTag_;
|
||||
};
|
||||
|
||||
struct EventAnimationDriverKey {
|
||||
|
||||
Reference in New Issue
Block a user