From 9320174df4239058125b8876a0623230f6e03b02 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Thu, 9 Nov 2023 11:38:54 -0800 Subject: [PATCH] Cxx TurboModules > Add example to return a JS function from Cxx to JS (#41385) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41385 Changelog: Internal Adding a Cxx TM example which adds a listener and returns a subscription to remove that listener from the TM. You should be able to use this with React Hooks - https://legacy.reactjs.org/docs/hooks-reference.html E.g. ``` useEffect(() => { const subscription = NativeCxxModuleExample.setValueCallbackWithSubscription( callbackValue => // use it ); return subscription; }); ``` Reviewed By: shwanton Differential Revision: D50473063 fbshipit-source-id: 4e9b92aeccff1771eb4ffad6bdaa20ba7f18435f --- .../NativeCxxModuleExample.cpp | 12 ++++++++++++ .../NativeCxxModuleExample/NativeCxxModuleExample.h | 8 ++++++++ .../NativeCxxModuleExample/NativeCxxModuleExample.js | 3 +++ .../TurboModule/NativeCxxModuleExampleExample.js | 10 ++++++++++ 4 files changed, 33 insertions(+) diff --git a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp index fb258b6022db60..78f45f47ef651f 100644 --- a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp +++ b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp @@ -20,6 +20,18 @@ void NativeCxxModuleExample::getValueWithCallback( callback({"value from callback!"}); } +std::function NativeCxxModuleExample::setValueCallbackWithSubscription( + jsi::Runtime& rt, + AsyncCallback callback) { + valueCallback_ = std::make_optional(callback); + return [&]() { + if (valueCallback_.has_value()) { + valueCallback_.value()({"value from callback on clean up!"}); + valueCallback_ = std::nullopt; + } + }; +} + std::vector> NativeCxxModuleExample::getArray( jsi::Runtime& rt, std::vector> arg) { diff --git a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h index fa160030783fc4..a13f8336b5fa9a 100644 --- a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h +++ b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h @@ -15,6 +15,7 @@ #include #endif #include +#include #include #include #include @@ -107,6 +108,10 @@ class NativeCxxModuleExample jsi::Runtime& rt, AsyncCallback callback); + std::function setValueCallbackWithSubscription( + jsi::Runtime& rt, + AsyncCallback callback); + std::vector> getArray( jsi::Runtime& rt, std::vector> arg); @@ -169,6 +174,9 @@ class NativeCxxModuleExample ObjectStruct getObjectAssert(jsi::Runtime& rt, ObjectStruct arg); AsyncPromise promiseAssert(jsi::Runtime& rt); + + private: + std::optional> valueCallback_; }; } // namespace facebook::react diff --git a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js index 93b03705253ea5..29936c5ca051fe 100644 --- a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js +++ b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js @@ -73,6 +73,9 @@ export interface Spec extends TurboModule { +getUnion: (x: UnionFloat, y: UnionString, z: UnionObject) => string; +getValue: (x: number, y: string, z: ObjectStruct) => ValueStruct; +getValueWithCallback: (callback: (value: string) => void) => void; + +setValueCallbackWithSubscription: ( + callback: (value: string) => void, + ) => () => void; +getValueWithPromise: (error: boolean) => Promise; +getWithWithOptionalArgs: (optionalArg?: boolean) => ?boolean; +voidFunc: () => void; diff --git a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js index b277a26f068afe..f4135cc5b5ffc3 100644 --- a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js +++ b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js @@ -77,6 +77,16 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> { NativeCxxModuleExample?.getValueWithCallback(callbackValue => this._setResult('callback', callbackValue), ), + callbackWithSubscription: () => { + const subscription = + NativeCxxModuleExample?.setValueCallbackWithSubscription( + callbackValue => + this._setResult('callbackWithSubscription', callbackValue), + ); + if (subscription) { + subscription(); + } + }, getArray: () => NativeCxxModuleExample?.getArray([ {a: 1, b: 'foo'},