logo

WebView — The Bridge that Connects React Native to the Web

May 01, 2019

WebView is the channel that connects React Native with Web platforms, giving us many great options to create a sort of connections to our app that is running on the Web!

asset 1

Using WebView element has a many of advantages it can be used for embedding or running a web application inside our React Native app that’s good especially if you have a web app and you want to connect that app the with your React Native app or even get access to the other platforms (google maps ex).

for a better understanding of the use cases of WebView, we are going to build a WebView that can load a web page and control the navigation!

Tip: Leverage components to build more modular software. Use tools like Bit (GitHub) to develop, share and reuse components between projects. It will help you build better applications faster alone or as a team, give it a try:

Share reusable code components as a team · Bit
_Easily share reusable components between projects and applications to build faster as a team. Collaborate to develop…_bitsrc.io

Getting started

Let start first by creating a new React Native project, make sure that you have the environment to run a React Native app. I’m using react-native-cli so all I need to do is to run the following command:

Note: you don’t need to create a new react-native app, you can just see the code and see how the WebView works I will leave to source good on GitHub

react-native init webview-app

This will bootstrap the project and all the necessary files to start working with React native.

Now run react-native run-ios to install the app on ios simulator and react-native run-android for Android.

For me, I have everything set up so I don’t have to run everything.

Implementing the WebView:

Note that WebView is an element of react-native that comes out of the box so no need for any extra configuration or installing any library so simply import it from react-native :

import { WebView } from "react-native"

And use it as any other elements:

import React, { Component } from "react"
import { StyleSheet, View, Text, ScrollView, WebView } from "react-native"

export default class Maps extends Component {
  render() {
    return (
      <View style={{ flex: 1 }}>
        <WebView />
      </View>
    )
  }
}

If you look at the screen it just now a blank screen!

asset 2

And that’s because the WebView requires a source URL in order to work! so let’s add the URL, we use source props to set the URL.

import React, { Component } from "react"
import { StyleSheet, View, Text, ScrollView, WebView } from "react-native"

export default class Maps extends Component {
  render() {
    return (
      <View style={{ flex: 1, backgroundColor: "red" }}>
        <WebView source={{ uri: "https://twitter.com" }} />
      </View>
    )
  }
}

I used here twitter as URL, and this will load the Twitter home page in our app 😉

asset 3

Actually, that’s super awesome just to be able to display a webpage inside your react-native app, and actually, you can use any other website as well, that’s mean also we have many options to control the WebView for example, handle the navigation.

Control the WebView

WebView, as we mentioned before, is just an element of react-native but there are options that let us do some tricks like even build a customized mini web browser Yeah!

Control the Layout

WebView is just a View that we can style and add an element to it, so we are going to add a header Component that can contain some other components, for example, a navbar to control the navigation! so let’s do it!

//@flow
import React, { Component } from "react"
import { StyleSheet, View, Text, ScrollView, WebView } from "react-native"

export default class Maps extends Component {
  render() {
    return (
      <View style={{ flex: 1 }}>
        <Header />
        <WebView source={{ uri: "https://twitter.com" }} />
      </View>
    )
  }
}

const Header = () => (
  <View style={styles.header}>
    <Text style={styles.title}>Profile</Text>
  </View>
)

const styles = StyleSheet.create({
  header: {
    paddingTop: 40,
    paddingBottom: 10,
    backgroundColor: "#0c084c",
  },
  title: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
  },
})

And voila!!

asset 4

Super cool, now let’s add a footer! the footer can contain, for example, a TabNavigator and some buttons to take some actions like goingBack and goForward

//@flow
import React, { Component } from "react"
import {
  StyleSheet,
  View,
  Text,
  ScrollView,
  TouchableOpacity,
  WebView,
} from "react-native"

export default class Maps extends Component {
  render() {
    return (
      <View style={{ flex: 1 }}>
        <Header />
        <WebView source={{ uri: "https://twitter.com" }} />
        <Footer />
      </View>
    )
  }
}

const Header = () => (
  <View style={styles.header}>
    <Text style={styles.title}>Profile</Text>
  </View>
)

const Footer = () => (
  <View style={styles.footer}>
    <TouchableOpacity>
      <Text style={styles.icon}>⬅️</Text>
    </TouchableOpacity>
    <TouchableOpacity>
      <Text style={styles.icon}>⭐️</Text>
    </TouchableOpacity>
    <TouchableOpacity>
      <Text style={styles.icon}> ➡️</Text>
    </TouchableOpacity>
  </View>
)
const styles = StyleSheet.create({
  header: {
    paddingTop: 40,
    paddingBottom: 10,
    backgroundColor: "#0c084c",
  },
  title: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
  },
  icon: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
  },
  footer: {
    padding: 20,
    flexDirection: "row",
    justifyContent: "space-around",
    backgroundColor: "#0c084c",
  },
})

The result !!

asset 5

Until now 👍!

Let’s add actions to the buttons so when a button is clicked, for example, allow to the page to navigate back that gives us some control on the navigation history.

  • If I click left-arrow it should take me back to the previous page if there is any
  • If I click the right-arrow it should navigate me to the next page if there is any.

In order to have control and use WebView navigation history, we have to assign it a ref to trigger those two actions:

//@flow
import React, { Component } from "react"
import {
  StyleSheet,
  View,
  Text,
  ScrollView,
  TouchableOpacity,
  WebView,
} from "react-native"

export default class Maps extends Component {
  state = {
    WEBVIEW_REF: "weViewRef",
  }
  goBack = () => {
    this.refs[this.state.WEBVIEW_REF].goBack()
  }
  goForward = () => {
    this.refs[this.state.WEBVIEW_REF].goForward()
  }

  render() {
    return (
      <View style={{ flex: 1 }}>
        <Header />
        <WebView
          source={{ uri: "https://twitter.com" }}
          ref={this.state.WEBVIEW_REF}
        />
        <View style={styles.footer}>
          <TouchableOpacity
            onPress={() => this.goBack()}
            disabled={this.state.canGoBack}
          >
            <Text style={styles.icon}>⬅️</Text>
          </TouchableOpacity>
          <TouchableOpacity>
            <Text style={styles.icon}>⭐️</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => this.goForward()}>
            <Text style={styles.icon}> ➡️</Text>
          </TouchableOpacity>
        </View>
      </View>
    )
  }
}

const Header = () => (
  <View style={styles.header}>
    <Text style={styles.title}>Profile</Text>
  </View>
)

const Footer = context => (
  <View style={styles.footer}>
    <TouchableOpacity>
      <Text style={styles.icon}>⬅️</Text>
    </TouchableOpacity>
    <TouchableOpacity>
      <Text style={styles.icon}>⭐️</Text>
    </TouchableOpacity>
    <TouchableOpacity>
      <Text style={styles.icon}> ➡️</Text>
    </TouchableOpacity>
  </View>
)
const styles = StyleSheet.create({
  header: {
    paddingTop: 40,
    paddingBottom: 10,
    backgroundColor: "#0c084c",
  },
  title: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
  },
  icon: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
  },
  footer: {
    padding: 20,
    flexDirection: "row",
    justifyContent: "space-around",
    backgroundColor: "#0c084c",
  },
})

And yeah😃

Control the page loading

Loading a page inside the WebView can be slow, and we want to display an indicator like a spinner to indicate to the user that the page is loading that gives the user a better experience. there are onLoadStart props that take a function that it’s called when the page starts loading and onLoadEnd that it’s called when the load end. so basically we are using those two methods to change states and display an indicator based on that state so we need to use a state.

We will use ActivityIndicator element from react-native to display the spinner!

state = {
  loading: false,
}
//@flow
import React, { Component } from "react"
import {
  StyleSheet,
  View,
  Text,
  ScrollView,
  TouchableOpacity,
  WebView,
  ActivityIndicator,
} from "react-native"

export default class Maps extends Component {
  state = {
    WEBVIEW_REF: "weViewRed",
    loading: false,
  }
  goBack = () => {
    this.refs[this.state.WEBVIEW_REF].goBack()
  }
  goForward = () => {
    this.refs[this.state.WEBVIEW_REF].goForward()
  }

  render() {
    return (
      <View style={{ flex: 1 }}>
        <Header loading={this.state.loading} />
        <WebView
          source={{ uri: "https://twitter.com" }}
          ref={this.state.WEBVIEW_REF}
          onLoadStart={() => this.setState({ loading: true })}
          onLoadEnd={() => this.setState({ loading: false })}
        />
        <View style={styles.footer}>
          <TouchableOpacity
            onPress={() => this.goBack()}
            disabled={this.state.canGoBack}
          >
            <Text style={styles.icon}>⬅️</Text>
          </TouchableOpacity>
          <TouchableOpacity>
            <Text style={styles.icon}>⭐️</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => this.goForward()}>
            <Text style={styles.icon}> ➡️</Text>
          </TouchableOpacity>
        </View>
      </View>
    )
  }
}

const Header = ({ loading }) => (
  <View style={styles.header}>
    <Text style={styles.title}>Profile</Text>
    {loading ? <ActivityIndicator color="blue" /> : null}
  </View>
)

const Footer = context => (
  <View style={styles.footer}>
    <TouchableOpacity>
      <Text style={styles.icon}>⬅️</Text>
    </TouchableOpacity>
    <TouchableOpacity>
      <Text style={styles.icon}>⭐️</Text>
    </TouchableOpacity>
    <TouchableOpacity>
      <Text style={styles.icon}> ➡️</Text>
    </TouchableOpacity>
  </View>
)
const styles = StyleSheet.create({
  header: {
    paddingTop: 40,
    paddingBottom: 10,
    backgroundColor: "#0c084c",
  },
  title: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
  },
  icon: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center",
  },
  footer: {
    padding: 20,
    flexDirection: "row",
    justifyContent: "space-around",
    backgroundColor: "#0c084c",
  },
})

Voila 💫

We still have many options and ability to do with WebView, for example, you can be integrated with the navigator of your app and make everything dynamic, I used webView in one of the applications I worked on, so when you click the thumbnail of a restaurant it redirects you to the restaurant gallery inside the WebView and here the WebView take a dynamic URL and that’s really useful because there was a web app do this job so I connected my React Native application with this web app through the WebView so I didn’t have to do the same twice .

Here is a list of props you can use:

Methods

Wrapping up

The WebView element is a powerful API through you can do magic things even like a mini Web Browser embedded inside your React Native app it’s a channel that will connect your apps in different platforms (mobile, Web)


More from me about React Native:

Discuss on Twitter 🐦

Here where I started!


Learn more

11 React Native Component Libraries You Should Know in 2019
_Useful React Native UI toolkits to use in your next app!_blog.bitsrc.io

5 Tools for Faster Development in React
_5 tools to speed the development of your React application, focusing on components._blog.bitsrc.io

How to Share React UI Components between Projects and Apps
_A simple guide to help you organize, share and sync React components between your team’s apps._blog.bitsrc.io

teambit/bit
_Easily share code between projects with your team. - teambit/bit_github.com