
As a React Native developer, you may be asked to implement features like redirecting to a web page or a different app within your React Native app. This can be achieved by using two modules from the React Native API: WebViews
and Linking
.
The WebView
component in React Native core first became available in React Native version 0.57.x
. Right now it is available as a community module and is often a default way to let the user visit external links within an iOS or an Android application.
The Linking
module allows you to handle deep links that can lead to other applications or use a native browser of the device. We'll show you both the WebView
component and the Linking
module in action below.
Prerequisites
To follow this tutorial, make sure you have the following installed:
- NodeJS (>=
8.x.x
) with npm or yarn installed as a package manager - expo-cli (>=
3.0.4
), previously known as create-react-native-app - JavaScript/ES6 basics
Please note that, throughout this tutorial, we’ll be using an iOS simulator to demonstrate the application.
Table of Contents
- Setting up a Crowdbotics app
- Setting up the React Native app
- Creating a simple WebView
- Adding Navigation between two screens
- Completing the WebView Screen
- Linking to other apps
- Handling deep links
- Conclusion
Setting up a Crowdbotics app
In this section, you will be setting up a Crowdbotics project that has React Native and an Expo generated template with stable and current dependencies for you to leverage. At the time of writing this tutorial, the template is based on Expo SDK version 32
. So instead of going into too much hassle about upgrading this React Native app, I will be walking you through creating a new React Native project in the next section.
To follow along, setting up a new project using Crowdbotics app builder service is easy. Visit the app.crowdbotics.com dashboard. Once you are logged in, choose Create New Application.

On the Create an Application page, choose React Native Expo template under Mobile App. Lastly, select the name of your app at the bottom of the page and then click the button Create my app!
After a few moments, your Crowdbotics project will be created. Upon its creation, it will redirect you to the app dashboard, where you can see a link to GitHub, Heroku, and Slack. Once your project is created, you will get an invitation from Crowdbotics to download your project or clone the repository from GitHub either via email or as a notification if you logged in using GitHub authentication.
Crowdbotics provides out-of-the-box solutions, including support and development of your application.
Setting up the React Native app
Once the app is generated and assuming you have either downloaded the project or cloned it in your local dev environment, navigate inside the directory. You will be welcomed by two sub-directories: backend
and frontend
. For this tutorial, you can ignore the backend
directory and open the frontend
directory in your favorite code editor or IDE.

One of the main reasons to use Expo for this tutorial is to have faster development setup. Crowdbotics' Expo app by default comes with a set of commonly used libraries in the React Native ecosystem. Some of these libraries are:
react-navigation
which you are going to see in action laternative-base
, one of the most popular UI component librariesredux
to manage the application's state
You can find the complete list of all the dependencies the project relies on inside the package.json
file. Now, to install these dependencies, execute the below command.
yarn install
# or
npm install
After installing all the dependencies, run the command yarn run start
and make sure either a simulator is running, or a real device is connected.
In this tutorial, you are not going to make use of Login
or Signup
screens that are provided by the Crowdbotics app. Let us make some changes in the navigation flow such that whenever the app reboots, it directly opens HomeScreen
as the first screen.
Open the src/navigators/HomeNavigator.js
file and modify it as follows:
import { createStackNavigator, createAppContainer } from 'react-navigation'
import Home from '../containers/Home'
const HomeNavigator = createStackNavigator({
Home: {
screen: Home,
navigationOptions: {
header: null
}
}
})
const HomeRootNavigator = createAppContainer(HomeNavigator)
export default HomeRootNavigator
In the above snippet, you are defining the HomeNavigator
as the root level app container. This navigator is based on StackNavigation
which is going to be useful when adding WebViews
.
Import the newly created HomeRootNavigator
inside the file App.js
. Replace the existing AppNavigator
with HomeRootNavigator
as shown in the snippet below.
import React, { Component } from 'react'
import { StatusBar } from 'react-native'
import { Provider } from 'react-redux'
import HomeRootNavigator from './src/navigators/HomeNavigator'
import store from './src/redux/store'
class App extends Component {
render() {
return (
<Provider store={store}>
<StatusBar barStyle='light-content' />
<HomeRootNavigator />
</Provider>
)
}
}
export default App
Now, when the app runs, you will be welcomed by the following Home screen, which is the default screen in Crowdbotics Expo generated apps.

Creating a simple WebView
To create a simple WebView component, all you have to do is import the WebView
component from React Native core inside the file src/containers/Home/index.js
file.
import React from 'react'
import { WebView } from 'react-native'
Then modify the functional Home
component in the same file with the following WebView
component.
const Home = () => <WebView source={{ uri: 'https://blog.crowdbotics.com' }} />
export default Home
The WebView
component requires a source
prop to load the static HTML in the form of a web page or a URI from a remote source where the web page already exists. You will get the following result.

Adding Navigation between two screens
In the previous demonstration, you can clearly observe that the WebView
component is currently loading the Crowdbotics blog from the URI. However, it's missing some basic navigation mechanisms, such as how to exit the Web view mode when the user is done interacting with the web page and go back to the application.
To enhance the current flow, in this section, you are going to add another container screen in the stack navigator that is going to take care of displaying the web view.
Create a new sub-directory inside src/containers
called WebViewScreen
. Next, inside this directory, create a new file called index.js
with the following code snippet. This component, for now, will act as a mock component for now.
import React, { Component } from 'react'
import { StyleSheet, View, Text } from 'react-native'
class WebViewScreen extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.text}>Webview Screen</Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
},
text: {
color: '#333',
textAlign: 'center'
}
})
export default WebViewScreen
You should also modify the Home
component. There is going to be a back button that will help navigate from the Home
screen to the WebViewScreen
when the navigation is added.
import React, { Component } from 'react'
import { Container, Content, Text, Button } from 'native-base'
import styles from './styles'
class Home extends Component {
state = {
title: 'Crowdbotics Blog',
link: 'https://blog.crowdbotics.com'
}
handleButtonPress() {
alert('You clicked')
}
render() {
const { title } = this.state
return (
<Container style={styles.container}>
<Content contentContainerStyle={styles.content}>
<Button onPress={this.handleButtonPress} style={styles.button}>
<Text style={styles.text}>{title}</Text>
</Button>
</Content>
</Container>
)
}
}
export default Home
In the above snippet, notice that the initial state object holds two properties: title
and link
. The title
is going to be displayed on the button as the text, and the link
is going to be passed to the WebViewScreen
to open the web page. Now run the application, and on the Home screen, there will be a button.

Clicking the button won't do any good for now. So let us add the navigation between the two screens, such that you can pass the navigational props.
Go to navigators/HomeNavigator.js
file and let us add the WebViewScreen
component.
import { createStackNavigator, createAppContainer } from 'react-navigation'
import Home from '../containers/Home'
import WebViewScreen from '../containers/WebViewScreen'
const HomeNavigator = createStackNavigator({
Home: {
screen: Home,
navigationOptions: {
header: null
}
},
WebViewScreen: {
screen: WebViewScreen,
navigationOptions: () => ({
headerTintColor: '#fff',
headerStyle: {
backgroundColor: '#0a1142'
}
})
}
})
const HomeRootNavigator = createAppContainer(HomeNavigator)
export default HomeRootNavigator
Stack Navigation provides a way to transit between screens. This mechanism works quite similar to how a web application works in a web browser. A web app either pushes (next page) or pops (go back) when navigating between different web pages in a browser. Similarly, different screens combined together are used to either push or pop in a React Native application using the stack navigation mechanism.
You will get the following result.

Notice that Stack Navigator from react-navigation
adds a default header if not specified. The WebViewScreen
utilizes this header
to navigate back to the Home
screen by clicking the back
button.
As the navigation between the two screens is working now, let's use navigation params to send the title from the Home
component's state to the WebViewScreen
. First, inside the HomeNavigator.js
file, modify navigationOptions
of WebViewScreen
by passing a navigation
argument and add a title
property to it.
WebViewScreen: {
screen: WebViewScreen,
navigationOptions: ({ navigation }) => ({
title: navigation.state.params.title,
// rest remains same
})
}
Next, go to the Home/index.js
file and pass the title
from the initial state as an object that is the second parameter to the navigation props.
handleButtonPress = () => {
const { title } = this.state
this.props.navigation.navigate('WebViewScreen', { title })
}
The navigation.state.params
allows reading the parameters passed through when handling the button press in the Home screen component. The props.navigation.navigate
is used to figure out which screen or route to visit when the button is pressed on the home screen. The name of the route or the screen is passed as the first argument as you can notice in the above snippet.
Now go back to the simulator device, and you will notice that the header on WebViewScreen
shows the title of the web page.

Completing the WebView Screen
Open the WebViewScreen.js
component file and edit it with only one WebView
component being returned inside the render
method.
import React, { Component } from 'react'
import { WebView, ActivityIndicator } from 'react-native'
class WebViewScreen extends Component {
LoadingIndicatorView() {
return (
<ActivityIndicator
color='#0a1142'
size='large'
style={{
flex: 1,
justifyContent: 'center'
}}
/>
)
}
render() {
const { params } = this.props.navigation.state
return (
<WebView
source={{ uri: params.link }}
renderLoading={this.LoadingIndicatorView}
startInLoadingState={true}
/>
)
}
}
export default WebViewScreen
The WebView
component from React Native uses props like startInLoadingState
and renderLoading
, which triggers the loading indicator—in our case, the function LoadingIndicatorView()
. This loading indicator is a pragmatic approach when a web page takes time to load.
Also note that in the above snippet, you will find another way to pass data between two screens. The WebViewScreen
is using navigation.state.params
to get the link
from the Home screen's initial state.
Will it work? The simple answer is no. Why? Because in the Home
screen component, you are not passing the link
yet as the second argument for the WebViewScreen
component to render its value.
Edit the following line inside Home/index.js
component.
handleButtonPress = () => {
const { title, link } = this.state
this.props.navigation.navigate('WebViewScreen', { title, link })
}
Now, go back to the simulator and press the button. It opens a new screen that displays the Crowdbotics' blog.

You see, it does take time to load the complete web page, and ActivityIndicator
component helps to display a spinner to convey the same message to the end-user of the application. This completes the WebView
section.
Linking to other apps
The WebView
component is great to render a third-party website within a React Native app. In the previous sections, you learned how to create and utilize the component from React Native's core.
As a mobile developer, there are going to be scenarios where you'll want to open the website or the link in the device's native browser or other native application. In these scenarios, you cannot use WebViews
. Also, these scenarios are known as deep linking and are more common in mobile applications.
React Native's core API provides another module called Linking
. This module allows interacting with other applications via deep links. It provides helper methods ready to use deep links in your current application. In the following sections, you are going to see it in action.
Open the Home/index.js
file and modify the initial state object. The object now contains an array called links
with three different items. Each item contains properties like title
to display the text on the button, and link
to designate the URI to follow when the button is clicked.
state = {
links: [
{
title: 'Native Browser',
link: 'https://blog.crowdbotics.com'
},
{
title: 'Text Message',
link: 'sms:+9910000000'
},
{
title: 'Email',
link: 'mailto:info@crowdbotics.com'
},
{
title: 'YouTube',
link:
'https://www.youtube.com/watch?v=ypdk64ySgoo&list=PLSk21zn8fFZBKEJxmkdSzzmMJrxkfyjph'
}
]
}
After modifying the initial state, let us move to the render function and display four buttons by mapping over the state.links
array. To avoid the warning in a yellow box, also add a key
prop to the Button
component. This prop will use the index
value since there is no unique identifier associated with any of the items in the links
array.
render() {
const { links } = this.state
return (
<Container style={styles.container}>
<Content contentContainerStyle={styles.content}>
{links.map((item, index) => (
<Button
onPress={() => this.handleButtonPress(item)}}
style={styles.button}
key={index}>
<Text style={styles.text}>{item.title}</Text>
</Button>
))}
</Content>
</Container>
)
}
Apart from traversing the array, the rest of the code remains the same. You will get the following result on a device.

Handling Deep Links
From the previous section, you know that whenever the user presses the button for each link, it will use the helper method called handleButtonPress
and pass the correct item from the state.links
array. This argument item
that is passed is then received by the handleButtonPress
as shown below.
handleButtonPress = item => {
Linking.openURL(item.link).catch(err =>
console.error('An error occurred', err)
)
}
Linking
module has a method to open external links. These external links can vary in nature, such as we have defined in the state of the Home
component. In the code snippet above, the method openURL
requires a valid URL to be passed for it to work. This method is promise-based, so using a catch
clause to catch errors or to display them is a good practice.
Let us test these out. Click the first button that says Native Browser
and it should open the link in the device's browser.

The default web browser opens, and it loads the website. There is no WebView
being used, so you do not have to add navigation strategy to handle this. Now, click on the button Text Message
and notice it should open the default SMS or text service application.

The third object in the links
array is to open the default Email client app. Since there is no email client app install on iOS simulator, I am going to show you the demo of running the application on a real Android device.

It works like a charm by opening the Gmail client app on the real device. Now, lastly, let us find out what happens when you click on the button that says YouTube. It will work in a similar manner and open the video link in the YouTube application.

Conclusion
By now, you understand how to create a WebView
component or use the Linking
module in your React Native application. Deep linking is important in mobile app development, and this tutorial provides you with an introduction on how to get started and not to get stuck in the beginning.
I hope this tutorial provided you an easy walkthrough to grab the basic concepts and build something of your own.
If you like this post, please leave a shoutout for me. I am always available on Twitter or you can check the rest of my tutorials here.
You will find the complete source code at this Github repository.