From be92588a7f673150f7cc0cf2503ecc78d9476bc2 Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Tue, 18 Mar 2025 12:12:03 -0700 Subject: [PATCH] Add EventPayload::extractValue for NativeAnimated (#49988) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49988 NativeAnimated currently depends on folly::dynamic event payloads for event-driven animations. While some events (e.g., ScrollEvent.h) have an `asDynamic` implementation, not all events do. In practice, NativeAnimated just needs to be able to extract an numeric value from a path to drive an animation. Rather than converting events to dynamic, or otherwise special casing event handling, this change allows arbitrary payloads to implement `EventPayload::extractValue` to retrieve JS property path values directly from events, without intermediate conversions to dynamic. ## Changelog [Internal] Reviewed By: javache Differential Revision: D71046682 fbshipit-source-id: 3544335ff9d50da87ced015de587b97204173b57 --- .../components/scrollview/ScrollEvent.cpp | 15 +++++++++++++++ .../renderer/components/scrollview/ScrollEvent.h | 3 +++ .../react/renderer/core/EventPayload.h | 13 +++++++++++++ 3 files changed, 31 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp index 9ade5490283..7adacc57527 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.cpp @@ -72,6 +72,21 @@ folly::dynamic ScrollEvent::asDynamic() const { return metrics; }; +std::optional ScrollEvent::extractValue( + const std::vector& path) const { + if (path.size() == 1 && path[0] == "zoomScale") { + return zoomScale; + } else if (path.size() == 2 && path[0] == "contentOffset") { + if (path[1] == "x") { + return contentOffset.x; + } else if (path[1] == "y") { + return contentOffset.y; + } + } + + return EventPayload::extractValue(path); +} + EventPayloadType ScrollEvent::getType() const { return EventPayloadType::ScrollEvent; } diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h index a17fd91c3ed..a9fccb459a6 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollEvent.h @@ -36,6 +36,9 @@ struct ScrollEvent : public EventPayload { */ jsi::Value asJSIValue(jsi::Runtime& runtime) const override; EventPayloadType getType() const override; + + std::optional extractValue( + const std::vector& path) const override; }; struct ScrollEndDragEvent : public ScrollEvent { diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventPayload.h b/packages/react-native/ReactCommon/react/renderer/core/EventPayload.h index a03405ae5a2..f0a00ac9196 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventPayload.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventPayload.h @@ -10,6 +10,8 @@ #include #include +#include +#include namespace facebook::react { @@ -33,6 +35,17 @@ struct EventPayload { * in `EventPayloadType` and return it from its overriden `getType()` method. */ virtual EventPayloadType getType() const = 0; + + /** + * Used to extract numeric values from the event payload based on + * property path names as they will exist in JavaScript. This can + * be used in conjunction with listeners on EventEmitters to do + * things like drive native animations. + */ + virtual std::optional extractValue( + const std::vector& /* path */) const { + return std::nullopt; + } }; using SharedEventPayload = std::shared_ptr;