<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CycleUse</title>
    <description>The latest articles on DEV Community by CycleUse (@cycleuse).</description>
    <link>https://dev.to/cycleuse</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3271176%2Fb7cf724d-3b9c-4b14-9305-f418c6151c1c.png</url>
      <title>DEV Community: CycleUse</title>
      <link>https://dev.to/cycleuse</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cycleuse"/>
    <language>en</language>
    <item>
      <title>Using a Marquee (Scrolling Text) as an Example: How React Native Calls and Controls a Native HarmonyOS Component via Fabric</title>
      <dc:creator>CycleUse</dc:creator>
      <pubDate>Thu, 26 Jun 2025 15:47:57 +0000</pubDate>
      <link>https://dev.to/cycleuse/using-a-marquee-scrolling-text-as-an-example-how-react-native-calls-and-controls-a-native-2i67</link>
      <guid>https://dev.to/cycleuse/using-a-marquee-scrolling-text-as-an-example-how-react-native-calls-and-controls-a-native-2i67</guid>
      <description>&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Overview: End-to-End Flow&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Walkthrough&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;RN Side: Declaring the Fabric Component&lt;/li&gt;
&lt;li&gt;Using the Component in RN&lt;/li&gt;
&lt;li&gt;Native HarmonyOS Side: ETS Implementation&lt;/li&gt;
&lt;li&gt;Native C++ Glue: Property and Event Binding for Fabric&lt;/li&gt;
&lt;li&gt;Native Event Emission Back to RN&lt;/li&gt;
&lt;li&gt;RN -&amp;gt; Native: Controlling Native State via Commands&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep Dive: The Fabric Architecture&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;What is Fabric?&lt;/li&gt;
&lt;li&gt;How Does Fabric Work?&lt;/li&gt;
&lt;li&gt;Benefits vs the Old Bridge&lt;/li&gt;
&lt;li&gt;How to Write Your Own Fabric Component&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Overview: End-to-End Flow
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fabric&lt;/strong&gt; is React Native's new rendering system, designed for performance and reliability. When integrating a custom native component like a "marquee" (text that scrolls horizontally) into a HarmonyOS app, Fabric allows React Native JS code to seamlessly declare, configure, and control the native view, while also receiving native events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JS/TS side&lt;/strong&gt;: Declare the component's props and events using &lt;code&gt;codegenNativeComponent&lt;/code&gt; (Fabric).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use in RN&lt;/strong&gt;: Import and use the component in a React Native screen, passing props and handling events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C++/Native bridge&lt;/strong&gt;: Properties and events are mapped automatically to native code via Fabric's codegen/binder logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HarmonyOS (ETS)&lt;/strong&gt;: The component is implemented as a HarmonyOS custom UI, which responds to JS props, emits events, and can be controlled via commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event emission&lt;/strong&gt;: Native can fire events, which are received in JS as callbacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command/control&lt;/strong&gt;: JS can send commands to control native component state at runtime (e.g., pause/resume marquee).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Code Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 RN Side: Declaring the Fabric Component
&lt;/h3&gt;



&lt;p&gt;```typescript name=MarqueeView.tsx&lt;br&gt;
import {&lt;br&gt;
    ViewProps,&lt;br&gt;
    HostComponent,&lt;br&gt;
} from 'react-native';&lt;br&gt;
import type { DirectEventHandler } from "react-native/Libraries/Types/CodegenTypes";&lt;br&gt;
import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";&lt;/p&gt;

&lt;p&gt;export type OnStopEventData = Readonly&amp;lt;{&lt;br&gt;
    isStop: boolean,&lt;br&gt;
    type: string,&lt;br&gt;
}&amp;gt;;&lt;/p&gt;

&lt;p&gt;export interface MarqueeViewProps extends ViewProps {&lt;br&gt;
    src: string, // The text to scroll&lt;br&gt;
    onStop?: DirectEventHandler; // Event from native&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;// Fabric codegen: registers 'MarqueeView' with property/event types&lt;br&gt;
export default codegenNativeComponent(&lt;br&gt;
    'MarqueeView',&lt;br&gt;
) as HostComponent;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


**Key Points:**

- `codegenNativeComponent` is critical: it tells React Native's codegen to generate all the glue for a Fabric component.
- `src` is a prop passed from JS to native.
- `onStop` is an event: native can call this to notify JS (e.g., when the marquee stops).

---

### 2.2 RN Usage: Using the Native Component in JS



```typescript name=GoodsMainPage.tsx (excerpt)
import MarqueeView from '../basic/MarqueeView';

function AppGoods() {
  const [marqueeStopped, setMarqueeStopped] = useState(false);
  const nativeRef = useRef&amp;lt;any&amp;gt;(null);

  // Listen for native events (DeviceEventEmitter also used for custom events)
  DeviceEventEmitter.addListener('clickMarqueeEvent', e =&amp;gt; {
    // ... handle custom event from native
  });

  return (
    &amp;lt;ScrollView&amp;gt;
      &amp;lt;View style={styles.container}&amp;gt;
        &amp;lt;MarqueeView
          src="Super Sale! Consumption is a key part of the social reproduction process..."
          ref={nativeRef}
          style={{ height: 180, width: '100%', backgroundColor: '#1980E6' }}
          onStop={e =&amp;gt; {
            setMarqueeStopped(e.nativeEvent.isStop);
          }}
        /&amp;gt;
        &amp;lt;GoodsButton
          buttonText={"Pause/Resume Marquee: " + (marqueeStopped ? "Stopped" : "Running")}
          onPress={() =&amp;gt; {
            // Send a command to native, using Fabric bridge
            UIManager.dispatchViewManagerCommand(
              findNodeHandle(nativeRef.current),
              'toggleMarqueeState',
              []
            );
          }}
        /&amp;gt;
      &amp;lt;/View&amp;gt;
    &amp;lt;/ScrollView&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Component used just like any RN component.&lt;/li&gt;
&lt;li&gt;Props (&lt;code&gt;src&lt;/code&gt;) go down to native.&lt;/li&gt;
&lt;li&gt;Event (&lt;code&gt;onStop&lt;/code&gt;) is handled as a callback.&lt;/li&gt;
&lt;li&gt;Native methods can be triggered via &lt;code&gt;UIManager.dispatchViewManagerCommand&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2.3 Native HarmonyOS Side: ETS Implementation
&lt;/h3&gt;



&lt;p&gt;```typescript name=MarqueeView.ets&lt;br&gt;
import { Descriptor, ViewBaseProps } from '@rnoh/react-native-openharmony';&lt;br&gt;
import { RNOHContext, RNViewBase } from '@rnoh/react-native-openharmony';&lt;/p&gt;

&lt;p&gt;@Component&lt;br&gt;
export struct MarqueeView {&lt;br&gt;
  static NAME: string = "MarqueeView"; // Matches JS codegen&lt;br&gt;
  ctx!: RNOHContext;&lt;br&gt;
  tag: number = 0;&lt;br&gt;
  @State private descriptor: Descriptor&amp;lt;"MarqueeView", MarqueeViewProps&amp;gt; = {} as any;&lt;br&gt;
  @State start: boolean = false;&lt;br&gt;
  @State src: string = "Default text";&lt;/p&gt;

&lt;p&gt;aboutToAppear() {&lt;br&gt;
    this.start = true;&lt;br&gt;
    // Listen for prop changes from RN&lt;br&gt;
    this.descriptor = this.ctx.descriptorRegistry.getDescriptor(this.tag);&lt;br&gt;
    this.ctx.descriptorRegistry.subscribeToDescriptorChanges(this.tag, (newDescriptor) =&amp;gt; {&lt;br&gt;
      this.descriptor = newDescriptor as MarqueeViewDescriptor;&lt;br&gt;
      this.src = (this.descriptor.rawProps as MarqueeViewProps).src;&lt;br&gt;
    });&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Listen for RN commands (e.g., pause/resume)
this.ctx.componentCommandReceiver.registerCommandCallback(this.tag, (commandName) =&amp;gt; {
  if (commandName === "toggleMarqueeState") {
    this.start = !this.start; // Toggle running state
    // Fire event back to RN
    this.ctx.rnInstance.emitComponentEvent(
      this.descriptor.tag,
      "onStop",
      { isStop: !this.start, type: "custom" }
    )
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;aboutToDisappear() {&lt;br&gt;
    this.start = false;&lt;br&gt;
    // Cleanup listeners...&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;build() {&lt;br&gt;
    RNViewBase({ ctx: this.ctx, tag: this.tag }) {&lt;br&gt;
      Column() {&lt;br&gt;
        Marquee({&lt;br&gt;
          start: this.start,&lt;br&gt;
          src: this.src&lt;br&gt;
        })&lt;br&gt;
        .onTouch(() =&amp;gt; {&lt;br&gt;
          // Emit a custom event to RN JS&lt;br&gt;
          this.ctx.rnInstance.emitDeviceEvent("clickMarqueeEvent", { params: { age: 18 } });&lt;br&gt;
        })&lt;br&gt;
      }&lt;br&gt;
      .height(180)&lt;br&gt;
      .justifyContent(FlexAlign.Center)&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


**Key Points:**

- The `MarqueeView` component receives props (`src`) from RN and reacts to command invocations (e.g., pause/resume).
- It can emit events (`onStop`) back to RN.
- Custom device events (via `emitDeviceEvent`) can be sent as well.

---

### 2.4 Native C++ Glue: Property and Event Binding for Fabric

#### Property Mapping



```cpp name=MarqueeViewJSIBinder.h
facebook::jsi::Object createNativeProps(facebook::jsi::Runtime &amp;amp;rt) override {
    auto object = ViewComponentJSIBinder::createNativeProps(rt);
    object.setProperty(rt, "src", "string"); // Expose 'src' to JS
    return object;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Event Mapping
&lt;/h4&gt;



&lt;p&gt;```cpp name=MarqueeViewJSIBinder.h&lt;br&gt;
facebook::jsi::Object createDirectEventTypes(facebook::jsi::Runtime &amp;amp;rt) override {&lt;br&gt;
    facebook::jsi::Object events(rt);&lt;br&gt;
    events.setProperty(rt, "topStop", createDirectEvent(rt, "onStop")); // Map native event to JS callback&lt;br&gt;
    return events;&lt;br&gt;
}&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


**Explanation:**

- `createNativeProps` tells Fabric which JS props are supported and their types.
- `createDirectEventTypes` registers which events the native component can emit, and how they're mapped back to JS.

---

### 2.5 Native Event Emission Back to RN

#### Native Event Emitter



```cpp name=MarqueeViewEventEmitter.h
class MarqueeViewEventEmitter : public ViewEventEmitter {
  public:
    using ViewEventEmitter::ViewEventEmitter;
    struct OnStop {
      bool isStop;
      std::string type;
    };

    void onStop(OnStop value) const;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;```cpp name=MarqueeViewEventEmitter.cpp&lt;br&gt;
void MarqueeViewEventEmitter::onStop(OnStop event) const {&lt;br&gt;
    dispatchEvent("stop", &lt;a href="https://dev.tojsi::Runtime%20&amp;amp;runtime"&gt;event = std::move(event)&lt;/a&gt; {&lt;br&gt;
        auto payload = jsi::Object(runtime);&lt;br&gt;
        payload.setProperty(runtime, "isStop", event.isStop);&lt;br&gt;
        payload.setProperty(runtime, "type", event.type);&lt;br&gt;
        return payload;&lt;br&gt;
    });&lt;br&gt;
}&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


**Explanation:**

- When the HarmonyOS component wants to notify RN (e.g., that the marquee has stopped), it calls `onStop`.
- This dispatches a JS event named `"stop"` with a payload containing `isStop` and `type`.
- The JS side receives this as the `onStop` callback.

#### Event Dispatching Handler



```cpp name=MarqueeViewEventEmitRequestHandler.h
void handleEvent(EventEmitRequestHandler::Context const &amp;amp;ctx) override {
    ArkJS arkJs(ctx.env);
    auto eventEmitter = ctx.shadowViewRegistry-&amp;gt;getEventEmitter&amp;lt;react::MarqueeViewEventEmitter&amp;gt;(ctx.tag);
    if (!eventEmitter) return;

    if (ctx.eventName == "onStop") {
        bool isStop = ...;
        std::string type = ...;
        react::MarqueeViewEventEmitter::OnStop event = {isStop, type};
        eventEmitter-&amp;gt;onStop(event);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2.6 RN -&amp;gt; Native: Controlling Native State via Commands
&lt;/h3&gt;



&lt;p&gt;```typescript name=GoodsMainPage.tsx (excerpt)&lt;br&gt;

  buttonText={"Pause/Resume Marquee"}&lt;br&gt;
  onPress={() =&amp;gt; {&lt;br&gt;
    UIManager.dispatchViewManagerCommand(&lt;br&gt;
      findNodeHandle(nativeRef.current),&lt;br&gt;
      'toggleMarqueeState', // Command name matches native implementation&lt;br&gt;
      [],&lt;br&gt;
    );&lt;br&gt;
  }}&lt;br&gt;
/&amp;gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


- The JS side can trigger imperative actions on the native component by sending commands.
- The native component listens for these commands (see `registerCommandCallback`) and updates its state accordingly.

---

## 3. Deep Dive: The Fabric Architecture

### 3.1 What is Fabric?

Fabric is React Native’s new rendering system that:

- Makes UI updates synchronous and more predictable.
- Uses a structure that mirrors the JS and native view trees (Shadow Tree).
- Leverages codegen for type-safe, fast prop/event bridging between JS and native.

### 3.2 How Does Fabric Work?

- **Component Registration**: In JS, you use `codegenNativeComponent` to declare your native view and its props/events.
- **Codegen**: React Native’s codegen tool scans these declarations and generates the C++/Java/ObjC glue code.
- **Property/Event Synchronization**: Updates to props/events are fast, type-safe, and avoid the old "bridge" serialization step.
- **Direct Command/Events**: Fabric supports direct commands and event emission between JS and native, reducing latency.

### 3.3 Benefits vs the Old Bridge

| Old Bridge          | Fabric                    |
| ------------------- | ------------------------- |
| Asynchronous        | Synchronous               |
| JSON Serialization  | Direct struct mapping     |
| Manual glue code    | Codegen-driven            |
| Potential for drift | Type-safe, always in sync |
| Slower, less robust | Faster, more reliable     |

### 3.4 How to Write Your Own Fabric Component

1. **JS/TS: Declare with `codegenNativeComponent`**
   - Define all props and events with proper types.
2. **Implement Native Component**
   - For HarmonyOS, write the ETS component.
   - For iOS/Android, implement their native UI logic.
3. **Binder/Glue (C++)**
   - Implement property and event mapping, usually with help from codegen.
4. **Use in JS**
   - Import and use your component like any other React Native component.

---

## 4. Summary

- **Fabric** enables seamless, high-performance integration of native components in React Native apps.
- The marquee example illustrates: property passing, event handling, and command-based control between RN and HarmonyOS via Fabric.
- **Best practices**: Always use codegen for new native components, keep prop/event naming consistent, and leverage Fabric's glue for robust, maintainable cross-platform UI code.

---

&amp;gt; **References**
&amp;gt;
&amp;gt; - [React Native New Architecture Guide](https://reactnative.dev/docs/architecture-overview)
&amp;gt; - [HarmonyOS JS/ETS Documentation](https://developer.harmonyos.com/en/docs/documentation/js-ets-overview)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
    <item>
      <title>Bidirectional Communication Between HarmonyOS ArkTS and React Native JS: Principles and Practices</title>
      <dc:creator>CycleUse</dc:creator>
      <pubDate>Tue, 17 Jun 2025 16:25:04 +0000</pubDate>
      <link>https://dev.to/cycleuse/bidirectional-communication-between-harmonyos-arkts-and-react-native-js-principles-and-practices-12pk</link>
      <guid>https://dev.to/cycleuse/bidirectional-communication-between-harmonyos-arkts-and-react-native-js-principles-and-practices-12pk</guid>
      <description>&lt;p&gt;This article focuses on explaining the principles and practices of bidirectional communication between HarmonyOS ArkTS and React Native JS, covering the complete path from the JS side to the ArkTS side and then to the C++ glue layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding the Overall Architecture
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JS Side (React Native Business Code):&lt;/strong&gt; The JS/TS files that developers write daily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C++ Glue Layer:&lt;/strong&gt; The bridging layer adapted for HarmonyOS, responsible for message and data transmission, working with TurboModule/JSI and other mechanisms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ArkTS Side:&lt;/strong&gt; The implementation of HarmonyOS native capabilities, pages, components, etc., responsible for the final business implementation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simplified communication flow diagram is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JS (RN) &amp;lt;==&amp;gt; C++ (Glue Layer) &amp;lt;==&amp;gt; ArkTS (Native)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  I. Full Flow of JS (RN) to ArkTS Communication
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 JS Side Calls TurboModule
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;(1) Declare TurboModule Interface&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/specs/v2/NativeCalculator.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;TurboModule&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native/Libraries/TurboModule/RCTExport&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;TurboModuleRegistry&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Spec&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;TurboModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;TurboModuleRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Spec&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RTNCalculator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Spec&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;(2) Actual Call&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RTNCalculator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rtn-calculator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;RTNCalculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// result should be 10, actually goes to native&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.2 C++ Glue Code Implements TurboModule
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;(1) Glue Header File Generation (Example)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// generated/RTNCalculator.h&lt;/span&gt;
&lt;span class="cp"&gt;#pragma once
#include&lt;/span&gt; &lt;span class="cpf"&gt;"RNOH/TurboModule.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;rnoh&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RTNCalculator&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ArkTSTurboModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="n"&gt;RTNCalculator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;(2) Method Implementation and Registration&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// generated/RTNCalculator.cpp&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"RTNCalculator.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;rnoh&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;RTNCalculator&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RTNCalculator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ArkTSTurboModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;methodMap_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"add"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[](&lt;/span&gt;&lt;span class="n"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;jsi&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;rt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;react&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TurboModule&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;turboModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;jsi&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Directly forward to ArkTS&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;static_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArkTSTurboModule&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;turboModule&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;callAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"add"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}}}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is equivalent to forwarding the parameters to the ArkTS side, where ArkTS implements the business logic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1.3 ArkTS Side Implements Capability
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// entry/src/main/ets/turbomodule/CalculatorModule.ets
import { TurboModule } from '@rnoh/react-native-openharmony/ts';
import { TM } from '@rnoh/react-native-openharmony/generated/ts';
export class CalculatorModule extends TurboModule implements TM.RTNCalculator.Spec {
  add(a: number, b: number): Promise&amp;lt;number&amp;gt; {
    return Promise.resolve(a + b);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.4 Return Result to JS Side
&lt;/h3&gt;

&lt;p&gt;ArkTS implements a Promise return, and the C++ glue automatically converts it to a JS Promise, allowing JS to obtain the final result.&lt;/p&gt;




&lt;h2&gt;
  
  
  II. Full Flow of ArkTS to JS (RN) Communication
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 ArkTS Side Sends Events to JS Side (DeviceEventEmitter Example)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ArkTS Side
this.ctx.rnInstance.emitDeviceEvent("customEvent", { foo: 123 });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.2 C++ Glue Code Forwards Events
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// C++ Implementation&lt;/span&gt;
&lt;span class="c1"&gt;// Corresponding to the internal emitDeviceEvent method&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;RNInstance&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;emitDeviceEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;folly&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;dynamic&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Actually calls the JS side's DeviceEventEmitter.emit through JSI&lt;/span&gt;
  &lt;span class="c1"&gt;// Pseudo code example:&lt;/span&gt;
  &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;jsCallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt; &lt;span class="c1"&gt;// Get the JSEmit function&lt;/span&gt;
  &lt;span class="n"&gt;jsCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.3 JS Side Listens for Events
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DeviceEventEmitter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;DeviceEventEmitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customEvent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// data = { foo: 123 }&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle messages sent from the ArkTS side here&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  III. JS (RN) Side Actively Listens for Native Events
&lt;/h2&gt;

&lt;p&gt;As above, the JS side listens for events actively pushed from the native side through DeviceEventEmitter or TurboModule's callback interface.&lt;/p&gt;




&lt;h2&gt;
  
  
  IV. Direct Message Communication Between ArkTS and JS (Message Bus Mechanism)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ArkTS Sends Message to C++ Side:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ArkTS
this.ctx.rnInstance.postMessageToCpp("SAMPLE_MESSAGE", { foo: "bar" });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C++ Glue Layer Observer Listens:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponentInstance&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;CppComponentInstance&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ArkTSMessageHub&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Observer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
  &lt;span class="n"&gt;MyComponentInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CppComponentInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;ArkTSMessageHub&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_deps&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;arkTSMessageHub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onMessageReceived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ArkTSMessage&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"SAMPLE_MESSAGE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Handle message.payload&lt;/span&gt;
      &lt;span class="c1"&gt;// Can then be forwarded to JS via emitDeviceEvent&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;C++ Sends Message to ArkTS Side:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;m_deps&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rnInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;postMessageToArkTS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ANOTHER_MESSAGE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ArkTS Side Listens for C++ Messages:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const unsubscribe = rnInstance.cppEventEmitter.subscribe("ANOTHER_MESSAGE", (value: object) =&amp;gt; {
  // value = { key: "value" }
  unsubscribe();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  V. Core Points Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For communication between RN (JS) and ArkTS, the &lt;strong&gt;C++ glue layer is the bridge&lt;/strong&gt;. Developers should mainly focus on the API usage on both ends.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JS side calls TurboModule method → C++ glue forwards → ArkTS implements capability → Promise returns to JS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ArkTS/Native side sends events → C++ glue forwards → DeviceEventEmitter/Event Bus → JS side listens and responds&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;message bus mechanism&lt;/strong&gt; supports bidirectional custom event/message passing, suitable for complex scenarios.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As long as you understand that "&lt;strong&gt;all communication must go through the C++ glue layer&lt;/strong&gt;" and make good use of TurboModule/DeviceEventEmitter/Message Bus, bidirectional communication between HarmonyOS ArkTS and React Native JS will become very clear and simple!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
