July 24, 2023
Photo by Lukasz Szmigiel on Unsplash Introduction A random forest is an ensemble model that…
As a React Native developer, you’re going to come across use cases that will require you to embed or redirect a web application or a web page inside a React Native app. WebViews are often used for such use cases.
A community-maintained module, WebViews in React Native are the only way to let the user visit external links within an iOS or Android application. The WebView component in React Native core first became available in React Native version 0.57.x
.
In this tutorial, you’re going to learn how to create a simple WebView component using the react-native-webview
npm module. You’ll also learn how to add custom navigation to handle URL history (just like in a web browser) using props provided by this module.
You can find the complete code for this tutorial at this GitHub repo.
<= 10.x.x
installed0.60.x
or aboveTo generate a new React Native project, you can use the react-native-cli
. open a terminal window and enter the following command:
npx react-native init [Project Name]
You can name your project anything you want. Make sure to navigate inside the project directory after it has been created. Then, install the react-native-webview
dependency using a package manager:
yarn add react-native-webview
After the dependency has been installed, you’re going to config it to work on iOS and Android devices. For iOS devices, make sure you install pods by navigating inside the ios/
directory and executing the command pod install
.
For Android users, if you’re using the latest react-native-webview
version (which you are) open the file android/gradle.properties
and make sure the following two lines exist. If not, add them:
android.useAndroidX=true android.enableJetifier=true
Once the dependency installation is done, let’s run the application. We’re going to use an iOS simulator for this tutorial. If you’re on Windows or Linux based operating systems, you can use Android Studio.
Run the command as stated below to open the boilerplate application that comes with the react-native-cli
:
# for Mac users react-native run-ios # for Windows/Linux users react-native run-android
If the app opens without any error, that means the configuration we have is good to go.
In this section, we’ll create a simple WebView
component and understand how it works. Start by importing the WebView
component from react-native-webview
to render web content in a native view. Open the App.js
file.
import React from 'react' import { SafeAreaView, StyleSheet, StatusBar } from 'react-native' import WebView from 'react-native-webview'
The WebView
component requires a source
prop. This prop loads the static HTML or a URI (which is the current case if you look closely at the above snippet). A URI is a remote location for a web page to exist.
Inside the App
function component, render this simple WebView component:
const App = () => { return ( <> <StatusBar barStyle='dark-content' /> <SafeAreaView style={styles.flexContainer}> <WebView source={{ uri: 'https://heartbeat.fritz.ai/' }} /> </SafeAreaView> </> ) } const styles = StyleSheet.create({ flexContainer: { flex: 1 } }) export default App
To view this in action, make sure you build the React Native app for the first time using either of the commands specified below from a terminal window. For Android users, if you’re using a real device or a simulator, make sure it’s running first. You’re going to see a similar output as below:
Did you notice that when the screen or the component loads for the first time, it just shows a blank white screen for a few seconds? This indicates that the web page is loading from the remote source. However, in a real-time application, you have to provide some type of loading indicator to the user to imply that the web page is being loaded.
This can be done by adding an ActivityIndicator
component from the react-native
core. It’s going to display a spinner on the device’s screen when the web page is loading.
In the App.js
file, among other imported components from react-native
, import ActivityIndicator
:
// ... rest of the import statements import { SafeAreaView, StyleSheet, StatusBar, ActivityIndicator } from 'react-native'
The ActivityIndicator
starts spinning when the web page starts to load and should stop when the web page is done loading.
The first requirement is that the prop startInLoadingState
from the react-native-webview
module must be set to a value of true. Another prop, renderLoading
, is responsible for triggering the activity indicator. It always accepts a function as its value. The value of the function is going to be the ActivityIndicator
component.
Add both of these props to WebView
in App.js
:
<WebView source={{ uri: 'https://heartbeat.fritz.ai/' }} startInLoadingState={true} renderLoading={() => ( <ActivityIndicator color='black' size='large' style={styles.flexContainer} /> )} />
Take a look at how it works on the below screen:
The WebView
has a vast API and out-of-the-box provides provides props to add basic features to your app. From the numerous methods, two are goBack
and goForward
to handle navigation state and transitions. The goBack
method allows the user to go back one page at a time in the web view’s history. Similarly, using the method goForward
, you can move forward one page at a time.
This navigation between web pages is done when there’s a way to store or listen to the URL change. Using the prop onNavigationStateChange
that represents the navigation state of the component, you just need to pass the current URL and keep track of the previous and forward buttons.
The current URL is passed by creating a ref
object, which is the approach you’re going to use in this demo app. It holds a mutable .current
property that can be used to uniquely identify the URL.
I’m going to use the latest Hooks syntax. If you’re using the counterpart of the functional components, please make sure to check how to use the ref
property on the WebView
instance inside the class component.
For those who have been following this tutorial so far, please make sure that you import Hooks such as
useRef
anduseState
from React.
Also, we’ll import some more components from the react-native core that’s going to help us add a footer to the app screen. This footer is going to have two buttons: one to go to the previous URL and one to go to the “forward” URL (if one exists).
import React, { useState, useRef } from 'react' import { SafeAreaView, StyleSheet, StatusBar, ActivityIndicator, View, TouchableOpacity, Text } from 'react-native' import WebView from 'react-native-webview'
Inside the functional component App
, let’s create three state variables for the following purposes:
canGoBack
: to go the previous web page from the navigational state. Its initial value is going to be a boolean false.canGoForward
: to go to the next web page in the navigational state. Its initial value is going to be a boolean false.currentUrl
: to keep a reference of the current URL. Its initial value is going to be an empty string.Let’s create these state variables inside the App
component:
const App = () => { const [canGoBack, setCanGoBack] = useState(false) const [canGoForward, setCanGoForward] = useState(false) const [currentUrl, setCurrentUrl] = useState('') //... }
Use the useRef
Hook to create a webviewRef
and define it after the state variables:
const webviewRef = useRef(null)
Now, create two handler methods that are going to handle the navigational state transition of the current URL in real-time using the mutable property current
on a button press:
backButtonHandler = () => { if (webviewRef.current) webviewRef.current.goBack() } frontButtonHandler = () => { if (webviewRef.current) webviewRef.current.goForward() }
Add the props ref
and onNavigationStateChange
to the WebView
component. The navState
is going to track the state changes and update it as well as fetch and set the current URL. This is shown in the code snippet below.
<WebView source={{ uri: 'https://heartbeat.fritz.ai/' }} startInLoadingState={true} renderLoading={() => ( <ActivityIndicator color='black' size='large' style={styles.flexContainer} /> )} ref={webviewRef} onNavigationStateChange={navState => { setCanGoBack(navState.canGoBack) setCanGoForward(navState.canGoForward) setCurrentUrl(navState.url) }} />
After the WebView
component, create a View
component that holds two buttons. Each of the buttons is defined from TouchableOpacity
, which has an onPress
prop. This prop is going to make use of the handler methods you defined earlier.
<View style={styles.tabBarContainer}> <TouchableOpacity onPress={backButtonHandler}> <Text style={styles.button}>Back</Text> </TouchableOpacity> <TouchableOpacity onPress={frontButtonHandler}> <Text style={styles.button}>Forward</Text> </TouchableOpacity> </View>
Here are the corresponding styles used in the above code snippet:
const styles = StyleSheet.create({ flexContainer: { flex: 1 }, tabBarContainer: { padding: 20, flexDirection: 'row', justifyContent: 'space-around', backgroundColor: '#b43757' }, button: { color: 'white', fontSize: 24 } })
To see it in action, go back to the simulator/device of your choice. The first thing you’ll notice is the bottom tab bar on the screen.
Here’s the complete demo in action with the back and forward buttons working.
Congratulations! You’ve completed this tutorial.
WebViews might not be the most prominent way to create mobile apps, but it does add an important feature to handle specific use cases where there’s a requirement to connect web interfaces and native code.
The WebView
component has a great API that you can refer to here.
You can find the complete code for this tutorial at this GitHub repo.
If you’d like to receive more React Native tutorials in your inbox, you can sign up for my newsletter here.