Milind Modi
Milind Modi

Reputation: 321

How can I send a data to webview by clicking on react native button

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  >

)}

Upvotes: 7

Views: 21744

Answers (6)

Deepak Singh
Deepak Singh

Reputation: 1145

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;

Upvotes: 0

gopher166
gopher166

Reputation: 137

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
 }  
}

Upvotes: 0

abhijithvijayan
abhijithvijayan

Reputation: 931

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

Upvotes: 6

Wayne Chiu
Wayne Chiu

Reputation: 6018

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')
});

Upvotes: 11

Jitendra Kumar
Jitendra Kumar

Reputation: 2221

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>
    );
  }
}

Upvotes: 1

Lakshman Kambam
Lakshman Kambam

Reputation: 1618

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>

Upvotes: 3

Related Questions