A project we recently worked on needed some complicated charts. We built those charts using JavaScript library and it worked fine on browsers.

Now we need to build mobile app using React Native and it would take a lot of time to build those charts natively. So we decided to use WebView to render the html pages which already displays charts nicely.

React Native comes with WebView component by default. So rendering the html page using WebView was easy. However, once the page is rendered the React Native app could not exchange any data with the web page.

In this blog post we’ll discuss how to make React Native app communicate with the pages rendered using WebView with the help of react-native-webview-bridge library.

What is React Native WebView Bridge ?

react-native-webview-bridge is a wrapper on top of React Native’s WebView component with some extra features.

First we need to install react-native-webview-bridge package.

npm install react-native-webview-bridge --save

Next we need to import the WebView bridge module.

// ES6
import WebViewBridge from 'react-native-webview-bridge';

// ES5
let WebViewBridge = require('react-native-webview-bridge')

Now let’s create a basic React component. This component will be responsible for rendering html page using WebView.

React.createClass({

  render: function() {
    return (
      <WebViewBridge
        ref="webviewbridge"
        onBridgeMessage={this.onBridgeMessage.bind(this)}
        source={ {uri: "https://www.example.com/charts"} } />
    );
  }
});

After the component is mounted then we will send data to web view.

componentDidMount() {
  let chartData = {data: '...'};

  // Send this chart data over to web view after 5 seconds.
  setTimeout(() => {
    this.refs.webviewbridge.sendToBridge(JSON.stringify(data));
  }, 5000);
},

Next, We will add code to receive data from web view.

onBridgeMessage: function (webViewData) {
  let jsonData = JSON.parse(webViewData);

  if (jsonData.success) {
    Alert.alert(jsonData.message);
  }
  console.log('data received', webViewData, jsonData);
  //.. do some react native stuff when data is received
}

At this time code should look something like this.

React.createClass({

  componentDidMount() {
    let chartData = {data: '...'};

    // Send this chart data over to web view after 5 seconds.
    setTimeout(() => {
      this.refs.webviewbridge.sendToBridge(JSON.stringify(data));
    }, 5000);
  },

  render: function() {
    return (
      <WebViewBridge
        ref="webviewbridge"
        onBridgeMessage={this.onBridgeMessage.bind(this)}
        source={ {
          uri: "https://www.example.com/charts"
        } } />
    );
  },

  onBridgeMessage: function (webViewData) {
    let jsonData = JSON.parse(webViewData);

    if (jsonData.success) {
      Alert.alert(jsonData.message);
    }
    console.log('data received', webViewData, jsonData);
    //.. do some react native stuff when data is received
  }
});

Okay, We’ve added all the React Native side of code. We now need to add some JavaScript code on our web page to complete the functionality.

Why do we need to add JavaScript snippet on my web page?

This is a two way data exchange scenario. When our React Native app sends any data, this JavaScript snippet will parse that data and will trigger functions accordingly. We’ll also be able to send some data back to React Native app from JavaScript.

The example in the README of WebViewBridge library shows how to inject JavaScript snippet in React component. However, we prefer JavaScript code to be added to web page directly since it provides more control and flexibility.

Coming back to our implementation, Let’s now add the snippet in our web page.

<script>
 (function () {
    if (WebViewBridge) {

      // This function gets triggered when data received from React Native app.
      WebViewBridge.onMessage = function (reactNativeData) {

        // Converts the payload in JSON format.
        var jsonData = JSON.parse(reactNativeData);

        // Passes data to charts for rendering
        renderChart(jsonData.data);

        // Data to send from web view to React Native app.
        var dataToSend = JSON.stringify({success: true, message: 'Data received'});

        // Keep calm and send the data.
        WebViewBridge.send(dataToSend);
      };
    }
  }())
</script>

Done! We’ve achieved our goal of having a two way communication channel between our React Native app and the web page.

Checkout this link for more examples of how to use WebView Bridge.