Web Development

Getting Started with VR in React Native with ViroReact

February 19th, 2019 | By Wern Ancheta | 9 min read

ViroReact is an open-source platform by Viro Media built to develop AR/VR applications with React Native.

VR and AR are promising technologies that, when implemented well, can improve how we experience things in the physical and virtual world.

From providing immersive experiences in entertainment and gaming to performing healthcare simulations in a virtual environment. This technology was made more accessible by platforms such as ViroReact. This platform allows us to implement VR and AR in a React Native app.

In this tutorial, we explore how you can use it to create a simple VR app. You can find the code for this tutorial on this GitHub repo.


Basic knowledge of React Native is required. Your machine should also be set up for plain React Native development (not Expo).

If you want to use ViroReact for iOS, you must have the latest version of Xcode installed. Also, ensure your manifest is updated to the most recent package versions (by running pod repo update).

If you want to use it for Android, be sure that you have the following installed for the SDK platforms:
And the following for SDK tools:
SDK-tools-React-Native-with-ViroReactThe rest is a standard requirement for React Native.

Since we are working with VR, I recommend you get your own Google Cardboard. You also need to install the Google Cardboard app. It will help you optimize your phone’s display for the specific viewer you’re using.

Lastly, sign up for a Viro Media API key. Fill out the form, and they will send the API key you can use on the app we are developing.

Basic concepts

ViroReact uses ARCore and ARKit behind the scenes.

ARCore is the AR development platform for Android, while ARKit is the iOS equivalent. Both use the device’s accelerometer and gyroscope to show the environment mapping as the device is moved. This allows an immersive experience.

Do note that ARCore and ARKit have limited support for devices:

But since we’re working with VR, the requirements are forgiving. If you have a pretty recent device (released within the past 3-5 years), you should be good.

ViroReact has two main components:

  • React components for VR and AR development: ViroReact has several custom React components that allow you to render different scenes, objects, and controls in a 3D environment.

  • High-performance native 3D rendering engine: ViroReact renders all objects with native device hardware acceleration. This means performance is good even though we’re using React Native.

App Overview

The app we are creating is a VR app that displays a park as a background, an image, and text.

We will also be animating the image so it becomes bigger. Here’s what it looks like:

Setting up the app

The first thing that you need to do is install the Viro CLI tool. This will allow us to generate a React Native project that has all the dependencies required for running VR/AR apps:

npm install -g react-viro-cli

Next, create a new project:

react-viro init RNViro --verbose

Once the project is created, navigate inside the RNViro directory and run ./setup-ide.sh:

cd RNViro
./setup-ide.sh --android

The option can either be --ios, --android, or --all.

Once that’s done, you can run the app. The Viro CLI tool includes a sample app when you bootstrap a new project. You can run the app via the Viro Media app:

npm start

Or via standard means:

react-native run-android --variant=gvrDebug

Note that we need to supply the --variant option of gvrDebug. This builds the debug version of the app which uses settings that are optimal for VR.

Building the app

Now we’re ready to build the app. As you can see, there’s already a “Hello World” sample app pre-created for you. All we have to do is edit it to accomplish what we want.

The first thing that we want to do is supply our API key because the app won’t run if we don’t supply it:

// App.js
var sharedProps = {

At this point, you can run the app on your device and look around. Be sure to enable live reload so the changes get reflected immediately every time you save.

Edit the code once you have an idea of what’s going on, and how the sample app works. We know that it first lets you choose the experience you want (whether VR or AR). But we want to get straight to VR, so we updated the render method to immediately return the VRNavigator:

render() {
  return this._getVRNavigator(); // replace everything inside render() with this

This renders the scene navigator for the VR experience. The scene navigator is the entry point of all Viro apps. There are only two types, ViroVRSceneNavigator (for VR) and ViroARSceneNavigator (for AR):

// App.js
import {
} from 'react-viro';

Going back to the _getVRNavigator() function, it simply renders the ViroVRSceneNavigator component. This requires the API key and the initialScene to be passed to it:

// App.js
_getVRNavigator() {
initialScene={{scene: InitialVRScene}}/>

The initialScene is what’s going to be initially displayed by this scene navigator. Think of scenes as pages of the app. If you’ve previously used React Navigation for navigating between the pages of your app, the idea is the same.

The scene that we’re using is in a different file which we have imported right below the declaration of the API key. This is where the main “meat” of the app we’ll be creating is:

 var InitialVRScene = require('./js/HelloWorldScene');

Open js/HelloWorldScene.js. First, import all the Viro components that we will be using. You’ll learn what each one does as we move along:

 import {
} from "react-viro";

Here’s the render method:

render() {
    return (
        <Viro360Image source={require("./res/360_park.jpg")} />
          position={[0, 0, -4]}
          animation={{ name: "animateImage", run: this.state.runAnimateImage }}
          text="Protect the client side!"
          position={[0, 0, -2]}
          outerStroke={{ type: "Outline", width: 8, color: "#333" }}

Now let’s break down the code above. In ViroReact, every scene needs to have a top-most component that wraps everything inside of it. ViroScene is one such component. It allows for the construction of a 3D environment so we can use components like the Viro360Image.

As the name suggests, the Viro360Image component is used for displaying a 360-degree photosphere. This uses the device’s gyroscope to display a specific part of the image based on the current orientation of the device:

  <Viro360Image source={require("./res/360_park.jpg")} />

The image we’re using above was downloaded from the ViroReact website. Choose from the available Photospheres and download it inside the js/res folder of the project. We’re specifically using the park image. You can also Google for “360-degree image”, and you’ll find lots of images that you can use with this component.

Next is the ViroImage component. This allows you to display plain old image files. Here we’re using it to display the Jscrambler logo. But, unlike the Viro360Image, we have to supply a few props for it to display properly:

position={[0, 0, -4]}
animation={{ name: "animateImage", run: this.state.runAnimateImage }}

Here’s what each prop does:

  • height and width - the height and width of the image in 3D space. The default value f 1 which basically means it will render the full size of the image. 2 means it will double, and so on. It’s best to resize the image to the size you wish to display it beforehand, and then preview it to make sure it’s not pixelated.

  • position - the cartesian position of the image in 3D space (x, y, and z positions). We’re used to the x and y positions, which represent the first and second values. But, in a 3D environment, there’s also a z dimension. This represents how near or far the image is within the viewing range. 0 means it’s just at the center of the viewing range, so -4 means it’s way back. This makes the user perceive the image as being far. Supplying a number that’s greater than 0 will make the image appear as if it were right in front of the user’s face. One thing that you need to remember about positioning is that 0 means center.

  • source - this is the same as the default React Native Image component. So you can either specify a local asset or a URL. In this case, it’s a local asset.

  • animation - the animation you want to perform to the image. This accepts an object containing the name of the animation and a boolean value run for specifying whether to run the animation or not. In this case, we’re using a value from the state to control when exactly it will animate. Later on, you’ll learn how we declare the name of the animation.

Next is the ViroText component. Just like the Text component in React Native, this is used to display text. Here, we’re supplying the same dimensions and positioning props that we used on the ViroImage component.

The only thing that might not be intuitive is the outerStroke. This allows you to put a background fill to the text so that it’s still pretty legible even though you have a very busy background (the 360-degree image):

text="Protect the client side!"
position={[0, 0, -2]}
outerStroke={{ type: "Outline", width: 8, color: "#333" }}

Now that we’re done walking through the different components, let’s add the one thing that we’re still missing: animation. Animations can be added to any component that’s displayed on the screen. Examples include the ViroImage and ViroText components.

Using animations in ViroReact is a two-step process. First, you have to register the animation; that is, give it a name and specify the animation itself. The animation to perform is specified under the properties property.

Here, we’re doing a scale animation. This scales the x (horizontal) and y (vertical) dimensions of the image. As you can imagine, the values we specified will elongate the image horizontally until it becomes twice its original width. While doing that, we also make the image smaller in height so it becomes 80% of its original height.

easing is the progression of the animation. EaseIn means that the animation will begin slowly and then speed up as it progresses. Lastly, the duration is how long the animation will take in milliseconds. In this case, we’re animating it over 3 seconds:

    animateImage: {
      properties: { scaleX: 2, scaleY: 0.8 },
      easing: "EaseIn",
      duration: 3000

Next, initialize the boolean value for controlling the start of the animation:

constructor() {
    this.state = {
      runAnimateImage: false

To run the animation, we update the state to true:

componentDidMount() {
    setTimeout(() => {
      this.setState({ runAnimateImage: true });
    }, 5000);

Lastly, we add the styles:

var styles = StyleSheet.create({
    textStyle: {
        fontFamily: "Arial",
        fontSize: 20,
        color: "#ffffff",
        textAlignVertical: "center",
        textAlign: "center"

Here’s what it will look like once you run the app:

VR app


That’s it! In this tutorial, you learned the basics of using ViroReact. Specifically, you learned how to create a basic VR application that displays a scene, an image, and a text.

ViroReact is a very promising solution for creating VR and AR apps in React Native. It allows you to develop VR/AR apps faster because of React Native’s fast live reload feature.

Aside from that, you don’t have to care about the differences in implementation between ARCore and ARKit because ViroReact already provides you with components you can use to create fast and truly immersive VR and AR apps.

If you're building React Native apps with sensitive logic, be sure to protect them against code theft and reverse engineering.


The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.

View All Articles

Must read next

Web Development

Getting Started with Animations in NativeScript

Animations are a key component of a great user experience in mobile apps. With this tutorial, you'll learn how to create animations in NativeScript.

April 11, 2019 | By Wern Ancheta | 10 min read


3 Methods for Getting Started with Functional Programming

If you’ve been keeping up with the hottest JavaScript trends out there you may have come across the concept of “Functional Programming”.

April 7, 2016 | By Jscrambler | 6 min read

Section Divider

Subscribe to Our Newsletter