7

I have used the componentDidMount method which sending data properly to webview but i want to send data webview when I click on particular react native button.

In this webview is displaying the local html page and in this I'm sending the data to webview and on load event in html page alert the data which sent by react native in this componentdidmount method is succesfully sending data to webview html page but when I'm trying same code in method which saying that this.input is undefined.

   export default class HtmlRender extends Component {

   //error:this.input is undefined
   sendData() {
         this.input.postMessage( data )
   }

// This Is working
 componentDidMount(){
         this.input.postMessage( data)
   }


 render(){
      return (
          <View style={styles.fullContainer}>
               <View style={styles.webviewBorder}  >

                  <WebView
                    ref={(input) => this.input = input}
                    source={{uri:'file:///android_asset/Page.html'}}
                   />
               </View>
           <View  >
                <Button  onPress={this.sendData}>
                   <Text>
                      Data
                   </Text>
               </Button>
            </View>
  </View  >

)}

6 Answers 6

11

In short

Sending Data from Native(Webview) to Web App

// Native
this.webviewRef.postMessage('Wayne is coming!!!')

// Web
window.addEventListener("message", message => {
  console.log(message.data) // Wayne is coming!!!
});

Sending data from Web App to Native(Webview)

// Web App
<button onClick={() => {
  if(window.ReactNativeWebView) { // ensure window.ReactNativeWebView is there, otherwise, web app might crash if is not there
    window.ReactNativeWebView.postMessage('Wayne is coming again')
  }
}}>
</button>

// Native App
<WebView
  onMessage={(event) => {
    console.log(event.nativeEvent.data) // Client received data
  }}
  source={{ uri: 'https://your.domain.com' }}
/>

Full Example React Native Code

import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
import { View, Button } from 'react-native';

class App extends Component {
  constructor(props) {
    super(props)
    this.webviewRef = null;
  }
  render() {
    return (
      <>
        <View style={{ flex: 1, alignContent: 'center', justifyContent: 'center' }}>
          <Button
            title="Press me"
            onPress={() => {
              this.webviewRef.postMessage('Wayne is coming!!!')
            }}
          />
        </View>
        <WebView
          onMessage={ (event) => {
            console.log(event.nativeEvent.data) // Client received data
          }}
          source={{ uri: 'https://your.domain.com' }}
          ref={ref => this.webviewRef = ref}
        />
      </>
    )
  }
}

Web App

// register an event listener
window.addEventListener("message", message => {
  console.log(message.data) // Wayne is coming!!!
  window.ReactNativeWebView.postMessage('Client received data')
});
Sign up to request clarification or add additional context in comments.

Comments

6

Unfortunately, for sending data from Native(Webview) to Web App with postMessage() method is deprecated in favour of injectJavaScript()

/**
 *  This script dispatches new custom messaging event
 */
function getInjectableJSMessage(message) {
  return `
    (function() {
      document.dispatchEvent(new MessageEvent('message', {
        data: ${JSON.stringify(message)}
      }));
    })();
  `;
}

// somewhere in your code
this.webviewRef.injectJavaScript(
    getInjectableJSMessage({
      message: 'Triggered event',
      triggeredAt: new Date(),
    })
);

In your webapp, register an event listener

function handleEvent(message) {
   console.log(message.data);
}

// This will only work for Android
// https://stackoverflow.com/a/58118984
document.addEventListener("message", handleEvent);

See related issue

2 Comments

This comment literally saved me days of searching through the web. Thank you
3

you can do it with injectedJavaScript. just define your html page source in const

const htmlData = require('./page.html');

and create a method like below

injectedToHtml() {
    const myData = {planet: 'earth', galaxy: 'milkyway'};
    let injectedData = `document.getElementById('container').value = '${myData.planet+myData.galaxy}';`;
    return injectedData;
   }

and return your web view like this in your component

<WebView
    source={htmlData}
    javaScriptEnabled={true}
    injectedJavaScript={injectedToHtml()}
    style={{flex: 1}}
/>

that's it! let me know if you still have any question.

your html file look like this..

<!DOCTYPE html>
<html>
    <head>
      <style>
          #container {
              width:100%;
              height:100vh;
              display: flex;
              align-items:center;
              justify-content: center;
          }
      </style>
    </head>
    <body>
        <div id="container"></div>
    </body>
</html>

9 Comments

Can this be possible on button click of react native .suppose if container data empty and i click on the react native button this will add the data in container
yeah you can do that. @MilindModi
let me create expo snack for you. I will send you once I finish.
just a quick question what if i want to change the variable data after loading the webview . can we change the data after that?
|
1

This is the simple code where you can send data to WebView on button click.

import React, { Component } from 'react';
import { Text, View, TouchableHighlight } from 'react-native';
import { WebView } from 'react-native-webview';

export default class App extends Component {
  constructor(props) {
    super(props);
  }

  sendDataToWebView() {
    let injectedData = `document.getElementById("login_field").value = '[email protected]';`;
    this.webView.injectJavaScript(injectedData);
  }

  render() {
    return (
      <View style={{ flex: 1, marginTop: 35 }}>

        <TouchableHighlight style={{ padding: 10, backgroundColor: 'gray', marginTop: 20 }} onPress={() => this.sendDataToWebView()}>
          <Text style={{ color: 'white' }}>Send Data To WebView from React Native</Text>
        </TouchableHighlight>

        <WebView
          style={{ flex: 1 }}
          source={{ uri: 'https://github.com/login' }}
          ref={(webView) => this.webView = webView}

        />
      </View>
    );
  }
}

Comments

0

To send data from React Native to Webview

React Native Code

constructor (props) { 
 super(props);
 this.state = {  }  
 this.webView = React.createRef();
}

sendDataToWebView = (dataObject) => {
  
 this.webView.injectJavaScript(`( function() { 
   document.dispatchEvent( new MessageEvent('message', { 
   data: ${JSON.stringify(dataObject)}, 
   origin : 'react-native' 
  })); })();` );
   
}

render() {
 return(
  <WebView
   source={{ ... }}
   containerStyle={{ ... }}
   ref={(webView) => this.webView = webView}
  />)
}

WebView Code

if(window.ReactNativeWebView) {
  window.addEventListener("message", this.webViewEventHandler); //android 
  document.addEventListener("message", this.webViewEventHandler); //ios
} 

webViewEventHandler = (event) => {
 if (event.origin == 'react-native'){
  console.log(event.data) //get dataObject
 }  
}

Comments

0

In my case, I'm using the React js and React Native

React native code below

import React, {useRef} from 'react';
import {Button, StyleSheet, Text, View} from 'react-native';
import {WebView} from 'react-native-webview';
import {vw} from '../../../utils/dimensions';

const UPIDisputesWebView = () => {
const webviewRef = useRef(null);

const sendDataToWebView = () => {
   const message = {name: 'through mobile application data', value: 123};

   const runSecondScript = `
     window.receiveDataFromReactNative('${JSON.stringify(message)}');
     true; 
    `;

 if (webviewRef.current != null) {
  webviewRef?.current?.injectJavaScript(runSecondScript);
 }

};

return (
  <View style={{flex: 1}}>
  <WebView
    ref={webviewRef}
    originWhitelist={['*']}
    source={{
      uri: 'http://localhost:5173/',  // your URL 
    }}
    style={styles.disputeWeb}
    javaScriptEnabledAndroid
    javaScriptEnabled={true}
    onMessage={event => {
      const dataFromWebView = JSON?.parse(event?.nativeEvent?.data);
      console.log('Message from WebView:', dataFromWebView);
    }}
  />

  <Button title="Send Data to WebView" onPress={sendDataToWebView} />
</View>
 );
};

 export default UPIDisputesWebView;

const styles = StyleSheet.create({
  disputeWeb: {flex: 1, opacity: 0.99, overflow: 'hidden'},
  bharatImage: {
  marginRight: vw(16),
  height: 20,
  width: 60,
  alignItems: 'flex-start',
  resizeMode: 'contain',
  },
 });

React js code below:

import React, { useEffect } from "react";

function App() {

 useEffect(() => {
  let data = "test running";
  window?.ReactNativeWebView?.postMessage(JSON.stringify(data)); // send data to react native

 // Get data from React Native
  window.receiveDataFromReactNative = function (data) {
    window?.ReactNativeWebView?.postMessage(JSON.stringify(data));
  };
 }, []);

  return <div>React js</div>;
}

export default App;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.