Trouble Sending Data from React Native to WebView-Rendered React App

214 Views Asked by At

I am working on a project where I need to send data (specifically gyroscope data) from a React Native app to a React app rendered inside a WebView. However, I'm facing difficulties in successfully transmitting this data. For simplicity reason I want to start by just sending a string and be able to access it in my react app.

What I Have Tried:

I have a React Native app that is supposed to send data to the React app. The React app is loaded inside a WebView in the React Native app. I attempted to use postMessage from React Native and listen for the message in the React app. Yet for some reason I am not able to find and use this data in my React App. he message/data doesn't seem to be received by the React app. I am not able to see any logs or data updates on the React app side.

Am I missing something in how I'm sending the data from React Native to the WebView? Is there a specific step or configuration required to enable communication between React Native and the WebView? Are there any known issues or limitations with using postMessage for this purpose?

React Native Code:

  const webViewRef = React.useRef<WebView>(null);


  return (
    <SafeAreaView style={styles.flexContainer}>
      <WebView
      ref={webViewRef}
      source={{ uri: 'http://localhost:3000/' }}
      startInLoadingState
      javaScriptEnabled
      allowsInlineMediaPlayback
      style={styles.flexContainer}
      onLoadEnd={() => webViewRef?.current?.postMessage("Hello")}
      />
    </SafeAreaView>
  );
};

And this is my React Code:

import React, { useState, useEffect, useRef } from 'react';
import './HolographicCard.css';

declare global {
  interface Window {
    ReactNativeWebView: {
      postMessage(message: string): void;
    };
  }
}

const HolographicCard = () => {
  const webViewRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    // Listen for messages from the WebView
    const messageListener = (event: MessageEvent) => {
      console.log('Message from WebView:', event.data);
    };

    window.addEventListener('message', messageListener);

    return () => {
      window.removeEventListener('message', messageListener);
    };
  }, []);

  async function navigateBackToApp() {
    window.ReactNativeWebView.postMessage('navigateBack');
  }

  return (
    <div className="card-container">
      <div className={`holographic-part`} ref={webViewRef}>
        {/* ... other content ... */}
      </div>
      <button className="success-button" onClick={navigateBackToApp}>
        Return
      </button>
    </div>
  );
};

export default HolographicCard;

1

There are 1 best solutions below

0
user18309290 On

Use injectJavaScript to interact with web and postMessage with React Native. Here is a super simple example:

export default App = () => {
  const html = `<html style="height: 100%;">
    <body style="height: 100%;">
      <div style="display: flex; justify-content: center; align-items: center; height: 100%;">
        <button id="button">Send to RN</button>
      </div>
      <script>
        document.getElementById("button").addEventListener("click", postMessage);

        function postMessage() {
          window.ReactNativeWebView.postMessage("Hello from HTML!")
        }

        function receiveMessage(message) {
          alert(message)
        }
      </script>
    </body>
  </html>`;
  const webref = useRef(null);

  const postMessage = (message) => {
    webref.current.injectJavaScript(`receiveMessage('${message}'); true;`);
  };

  const receiveMessage = (message) => {
    console.log(message);
  };

  return (
    <View style={{ flex: 1 }}>
      <WebView
        ref={webref}
        source={{ html }}
        onMessage={(event) => receiveMessage(event.nativeEvent.data)}
      />
      <Button
        title="Send to web"
        onPress={() => postMessage('Hello from RN!')}
      />
    </View>
  );
};

See Communicating between JS and Native for details.