Learn React VR (Chapter 2 | Panoramic Road Trip)

Prerequisites

Chapter 1 | Hello Virtual World

Scope of This Chapter

In the previous chapter, we were able to get an introduction to React VR and display a beautiful panoramic photo of the Horseshoe Bend.

In this chapter, we will be going over features of React components in React VR. We will see what is the same and what is different. Specifically, we will be looking into using Flexbox to control our layout.

At the end of this chapter, we will create an interactive VR app called Panoramic Road Trip. This app will allow us to select a destination from a menu and visit that destination in a 360-degree experience.

I hope you’re as excited as I am. Let’s get started.

Encapsulating Data

Just like standard React, React VR allows us to encapsulate data in a component either with props or state. We will go through an example of each just to see this in action.

Props

props are used for data that is read-only. In other words, it’s used for data that will not be changed. Currently, our HelloVirtualWorld component in our index.vr.js file contains read-only text:

<Text> Hello Virtual World </Text>

Let’s replace this using props.

First, let’s create a new component called NestedMessage:

class NestedMessage extends React.Component {
render() {
return (

);
}
};

After that, go ahead and cut the Text component in HelloVirtualWorld and paste it in the return of NestedMessage:

class NestedMessage extends React.Component {
render() {
return (
<Text
style={{
backgroundColor: '#777879',
fontSize: 0.8,
fontWeight: '400',
layoutOrigin: [0.5, 0.5],
paddingLeft: 0.2,
paddingRight: 0.2,
textAlign: 'center',
textAlignVertical: 'center',
transform: [{translate: [0, 0, -5]}],
}}>
Hello Virtual World
</Text>
);
}
};

Now, let’s nest NestedMessage and pass down a prop within the HelloVirtualWorld component:

export default class HelloVirtualWorld extends React.Component {
render() {
return (
<View>
<Pano source={asset('horseshoe-bend.jpg')}/>
<NestedMessage message={"Hello Nested Message"}/>
</View>
);
}
};

Next, we can use this message prop as our text:

<Text style={{...}}>{this.props.message}</Text>

If you have taken a break in between chapters, open our project in command line and run:

npm start

We should now see the message prop displayed as the text:

Perfect! That was easy.

State

state is used whenever we have data that will be updated.

Let’s have our text in NestedMessage be controlled by the local state instead of using props. Then, we will test out updating the state so we can change the text.

First things first, you can remove the message prop:

<NestedMessage/>

Then, let’s add a constructor with this.state defined in our NestedMessage component:

class NestedMessage extends React.Component {
constructor() {
super();
this.state = {};
}

//render function here
};

Next, we can add a property in our state called message:

this.state = {message: "Hello State Message"};

Finally, we will change this.props.message to this.state.message:

{this.state.message}

As we’d expect, we can now see our message which is controlled by the local state:

Sweet! Now, let’s try to update the message.

To update the message, we will add a setTimeout in our constructor that will set a new state with an updated message after 5 seconds:

class NestedMessage extends React.Component {
constructor() {
super();
this.state = {message: "Hello State Message"};
setTimeout(() => {
this.setState({ message: "Hello Updated Message" });
}, 5000);
}
  //render function here
};

Refresh the localhost and we should see this works as expected:

Cool beans! Before we continue, make sure to remove the setTimeout in our constructor.

Event Handling

props and state were just like what we are used to in standard React.

Event handling also works similar but there’s going to be new concepts to cover.

First off, what types of events are available?

To answer this, we can click on a component that we want to apply event handling to from the menu in the official React VR docs.

Let’s check some possible events that we can handle for the Text component we have been playing around with.

In the documentation above, you’ll see to events that we can handle: onLongPress and onPress.

Press refers to a touch screen event. I don’t have a touch screen computer so we need to find a way around this.

React VR has component called VrButton. Unlike an HTML button, it has no appearance by default and is to be wrapped around another component when we want to capture button-like events.

For example, our Text component only has press events. If we wrapped VrButton around it, we could have the effect of clicking on our text and triggering an event handler even though the event was technically captured in VrButton.

This is hard to visualize without seeing the code so let’s get to it.

Let’s test this out in our NestedMessage component.

First, we import VrButton:

import {
AppRegistry,
asset,
Pano,
Text,
View,
VrButton
} from 'react-vr';

Then, let’s wrap a VrButton component around our current Text component:

<VrButton>
<Text style={{...}}>
{this.state.message}
</Text>
</VrButton>

In addition, we now have a Text component and a VrButton component within our NestedComponent render function. Therefore, we need to wrap these around an outermost <View> component like we would wrap an outermost <div> element in standard React:

<View>
<VrButton>
<Text style={{...}}>
{this.state.message}
</Text>
</VrButton>
</View>

Next, we will add the method that will handle the onClick event. In this method, we want to update the local state with a new message:

//constructor here
handleClick () {
this.setState({ message: "Updated Message" });
}

Now, we want to setup the event trigger in the opening tag of our VrButton component:

<VrButton 
onClick={this.handleClick.bind(this)}
>
<Text>Click me!</Text>
</VrButton>

Note that we bind this so we can call our event handling methods using this.handleClick.

Save your changes and refresh the localhost.

Woohoo! We’ve handled our first event in React VR!

Now, we need to cover 3 more component features before we process. Those features being lifecycle hooks, conditional rendering, and layout.

Lifecycle Hooks

This step is really easy. Let’s just test using a React lifecycle to update our message:

//constructor here
componentDidMount () {
this.setState({ message: "Mounted" });
}

We should see this working with no issues:

No changes here so let’s move on.

Conditional Rendering

Let’s also test conditional rendering in React VR.

First, let’s add a boolean flag to our state called showMessage and set it to true by default:

this.state = {message: "Hello State Message", showMessage: true};

Next, let’s store this in a variable in our render function:

render() {
const showMessage = this.state.showMessage;
//return here
}

Then, let’s return our message display if showMessage is true and return an empty Text component (show nothing) if showMessage is false:

return (
<View>
{showMessage ? (
<VrButton onClick={this.handleClick.bind(this)}>
<Text
style={{
backgroundColor: '#777879',
fontSize: 0.8,
fontWeight: '400',
layoutOrigin: [0.5, 0.5],
paddingLeft: 0.2,
paddingRight: 0.2,
textAlign: 'center',
textAlignVertical: 'center',
transform: [{translate: [0, 0, -5]}],
}}
>
{this.state.message}
</Text>
</VrButton>
) : (
<Text></Text>
)}
</View>
);

Finally, let’s update showMessage to false in the lifecycle we just created:

componentDidMount () {
this.setState({ showMessage: false });
}

Now, we should see that the message does not appear after our component mounts:

Flexbox Layout

Creating any user interface requires organization of the layout. With a grid system, like react-grid-system which I describe here, you organize the user interface into rows and columns.

For example, let’s say we want to display the following section:

In terms of rows and columns, this section would be 1 row and 2 columns:

In a complete user interface with React, each section will be a component that defines the layout in terms of rows and columns.

With a grid system, you have to define the width of each column.

For instance, Bootstrap’s grid system allows you to define the width of columns in a way that gives you all of the following options for a row:

Understanding Flexbox Basics

Flexbox layout in React VR works a bit differently as it is meant to make the layout more flexible.

Let’s explain these concepts behind Flexbox using some nice visual aids.

With Flexbox, we start off with a container with a specified width:

Then, we would specify the direction of our container (if we want the container to be a row or column).

Here’s an example of a row direction:

Here’s an example of a column direction:

Let’s say we specified a row, Flexbox invisibly draws a horizontal main axis line like so:

As we add items in our container, the items will be added in the direction of this main axis. In the case of a row, items are added horizontally. In the case of a column, items are added vertically.

Continuing with our row example, let’s add 3 items:

By default, Flexbox will fit all the items in one line of the container. Therefore, if we wanted to add another box to our container shown above, all the boxes would shrink so they all fit:

When the main axis is drawn by Flexbox, there is a cross axis that runs perpendicular to the main axis:

If we specified a column direction, the main axis would be running vertically and the cross axis would be running horizontally.

Putting it all together, here’s the final visualization of our row:


This concludes the basic principles behind Flexbox. However, there’s still a bit more to cover.

Let’s discuss it more as we use Flexbox layout to display 5 Text components in a column in our virtual world.

Creating a New Project

We will create a new project for the VR app we want to create by the end of this chapter called Panoramic Road Trip.

In this new project, we will start off by adding our 5 Text components in a column using Flexbox layout.

Change directories in command line to where you want the new project folder created.

Then, run the following:

react-vr init PanoramicRoadTrip

Once that is finished, add the project folder to Atom and open index.vr.js.

Implementing Flexbox Layout

Let’s start by removing the default Text component so we just have:

<View>
<Pano source={asset('chess-world.jpg')}/>
</View>

Then, copy horseshoe-bend.jpg from the static_assets folder in HelloVirtualWorld to the static_assets folder in our new project.

After that, update the Pano component’s source:

<Pano source={asset('horseshoe-bend.jpg')}/>

Now, we are ready to start working with Flexbox.

Underneath our Pano component, we need to add an outermost View component that will be the Flex container for all of our Text components:

<View>
<Pano source={asset('horseshoe-bend.jpg')}/>
<View>
</View>
</View>

Next, let’s specify the width of our View component:

<View
style={{
width: 2
}}
>
</View>

The units in React VR styling is in meters. We are specifying our Flex container to have a width of 2 meters.

We want to make this container a column, so we can add a flexDirection value:

<View
style={{
width: 2,
flexDirection: 'column'
}}
>
</View>

At this point, our View container looks like this under the hood:

Next, we want to specify how we want to align and justify our items within this column container. This is where we will have to expand beyond the basics of Flexbox that we covered earlier.


The property to align our items is itemAlign.

itemAlign refers to how items will be laid out across the cross axis.

There are 4 possible values to align our items with Flexbox in React VR: stretch, flex-start, center or flex-end .

stretch means that the items will stretch to fill the container along the cross axis.

For example, items within a column container would stretch like this:

Note the height of this item would be specified manually. Also, stretch is the default value in Flexbox.

flex-start means that items would be laid out at the start of the cross axis. This will be the very left point for a column and the very top point for a row.

Let’s say we had specified a manual width for an item that was 50% of a column container. The item could be laid out like this:

flex-end would lay out the items at the end of the cross axis:

center will have items centered on the cross axis:

How an item is laid out across the main axis is specified by the property called justify-content.

In React VR, this can have 3 possible values: flex-start, space-around or space-between .

flex-start means that the items will be laid out starting at the top of the main axis.

In a column container, if the item was aligned on the center of the cross axis and justified using flex-start, we would see the following:

space-between means that the items would be justified evenly across the main axis with the first item on the start and the last item on the end:

space-around means that the items would be justified evenly across the main axis and equal space around the start and end:


With the discussion of aligning and justifying items out of the way, let’s return to our code which looks like this at the moment:

First, let’s specify that we want our View component to have a stretch alignment:

<View
style={{
width: 2,
flexDirection: 'column',
alignItems: 'stretch'
}}
>
</View>

Next, let’s justify our content using flex-start:

<View
style={{
width: 2,
flexDirection: 'column',
alignItems: 'stretch',
justifyContent: 'flex-start'
}}
>
</View>

Then, add a transform with a negative Z value that will have our column appear 5 meters away:

<View
style={{
width: 2,
flexDirection: 'column',
alignItems: 'stretch',
justifyContent: 'flex-start',
transform: [{translate: [0, 0, -5]}]
}}
>
</View>

Finally, we can finish off the styling for our View component by putting a layout origin that will position this container in the vertical and horizontal center of our virtual world:

<View
style={{
width: 2,
flexDirection: 'column',
alignItems: 'stretch',
justifyContent: 'flex-start',
transform: [{translate: [0, 0, -5]}],
layoutOrigin: [0.5,0.5]
}}
>
</View>

With that out of the way, let’s add 5 Text components. We will need to wrap these Text components around View components. We can think of it as defining a text box and then injecting the actual text.

We are going to have Text components for 5 states:

  • Arizona
  • New Hampshire
  • California
  • Hawaii
  • Texas
<View
style={{
flex: 1,
width: 2,
flexDirection: 'column',
alignItems: 'stretch',
layoutOrigin: [0.5, 0.5],
transform: [{translate: [0, 0, -5]}]
}}
>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>Arizona</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>New Hampshire</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>California</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>Hawaii</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>Texas</Text>
</View>
</View>

In the code above, we include some simple styling for our text boxes (View components with a nested Text component) and our text (Text components).

If we go to our local host and refresh, we can see this is now rendering as:

Awesome!

So, how is this working according to Flexbox again?

Well, we defined a column so the main axis direction is flowing down:

The cross axis runs horizontally.

The item alignment was specified as stretch so our items expand to the full width of the container which was 2 meters (the cross axis).

Our content was justified using flex-end so our items were laid out starting at the top of the main axis.

Here’s a visualization of the text boxes in relation to our column:

Pretty cool, huh? The last thing to do is to have these text boxes be there own component.

Let’s add the shell of this new component in our index.vr.js:

class TextBoxes extends React.Component {
render() {
return (
<View>

</View>
)
}
}

Then, we can copy the text boxes with their nested text within the outermost View component shown above:

class TextBoxes extends React.Component {
render() {
return (
<View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>Arizona</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>New Hampshire</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>California</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>Hawaii</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>Texas</Text>
</View>
</View>
)
}
}

Finally, let’s nest this new TextBoxes component into our PanoramicRoadTrip component:

export default class PanoramicRoadTrip extends React.Component {
render() {
return (
<View>
<Pano source={asset('Arizona.jpg')}/>
<View
style={{
flex: 1,
width: 2,
flexDirection: 'column',
alignItems: 'stretch',
layoutOrigin: [0.5, 0.5],
transform: [{translate: [0, 0, -5]}]
}}
>
<TextBoxes/>
</View>
</View>
);
}
};

With this aside, let’s finish out our Panoramic Road Trip app.

Finishing Our Panoramic Road Trip

So far, we have a single static panoramic photo that renders along with our newly added text boxes.

We want to be able to render different panoramic photos depending on the current state. When the component mounts, a random state will be selected. Depending on the selected state, we will have to render the proper panoramic photo. We will also include a title Text component above these text boxes that updates to the name of the current state in reaction to our clicks.

Let’s get to it.

Passing Down Props

First off, let’s have the text for our states be controlled by props since they are read-only data.

To do this, we can start by creating an object in the render function of the PanoramicRoadTrip component:

export default class PanoramicRoadTrip extends React.Component {
render() {
const states = {
Arizona: "Arizona",
NewHampshire: "New Hampshire",
California: "California",
Hawaii: "Hawaii",
Texas: "Texas"
}
//return here
}

Then, we can pass down this object to the TextBoxes component so all the states will be available as props:

<TextBoxes states={states}/>

Now, we can use these props to inject the text for our states:

class TextBoxes extends React.Component {
render() {
return (
<View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>{this.props.states.Arizona}</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>{this.props.states.NewHampshire}</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>{this.props.states.California}</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>{this.props.states.Hawaii}</Text>
</View>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>{this.props.states.Texas}</Text>
</View>
</View>
)
}
}

Adding a Title

Now, let’s create a new component called Title which we will nest into the same column container as these text boxes.

First, we can add the shell for the new component:

class Title extends React.Component {
render() {
return (
<View>

</View>
)
}
}

Then, let’s add a Text component that will display the title:

<View>
<Text
style={{
fontSize: 0.2,
textAlign: 'center',
color: "#CF3C7E"
}}
>
  </Text>
</View>

Since we want to have the value of our title update, we need to create a local state that defines the value of the title:

class Title extends React.Component {
constructor() {
super();
this.state = {title: "Panoramic Road Trip"};
}
//render function
}

Finally, let’s inject title as defined in out state in the Text component:

<Text style={{fontSize: 0.2, textAlign: 'center', color: "#CF3C7E"}}>
{this.state.title}
</Text>

Now that our Title component is defined, let’s nest it right above our TextBoxes component in our PanoramicRoadTrip component:

<Title/>
<TextBoxes states={states}/>

If we check our local host and refresh, we should now see the following:

Random Selection of a Panoramic

In this step, we want to add a lifecycle hook for when our component mounts. In this lifecycle hook, we will choose a random number between 1 and 5. Depending on the result, a state (i.e. California) will be selected and the appropriate panoramic photo will be rendered.

This means we have to add a local state that controls defines the selected state and the source for panoramic photo we want to render.

First things first, go ahead and download all the photos and add them to the static_assets folder of our Panoramic Road Trip project.

You will notice that the photo files are named after the states.

Next, let’s add the following constructor to our PanoramicRoadTrip component:

constructor() {
super();
this.state = {selectedState: ""};
}

selectedState will be Arizona, New Hampshire, California, Hawaii, or Texas.

This will be updated in a lifecycle hook where we pick a random state to be selected.

Let’s add that lifecycle hook now:

//in PanoramicRoadTrip component
componentDidMount() {
const random = Math.floor((Math.random() * 5) + 1);
let randState;
switch(random) {
case 1:
randState = "Arizona";
break;
case 2:
randState = "New Hampshire";
break;
case 3:
randState = "California";
break;
case 4:
randState = "Hawaii";
break;
case 5:
randState = "Texas";
break;
}
this.setState({ selectedState: randState});
}

In this code, we are saying: “Hey! When our app mounts, let’s get a random number between 1 and 5. Depending on that random number, let’s update our selectedState.”

Next, we can use that selected state as to choose our panoramic photo since they possess the same naming. We will just have to append the “.jpg” like so:

<Pano source={asset(this.state.selectedState + '.jpg')}/>

Save your code and try refreshing the local host. We should get a random panoramic each time:

Adding Our Event Handler

The next step is going to be to add our event handler which will ultimately update the panoramic photo.

We need to have a function that is called on the click of our text boxes in our TextBoxes component which then updates the selectedState property in our PanoramicRoadTrip component.

Recall, we earlier wrapped a VrButton component around a Text component in order to have an onClick event captured. In our case, we need an onClick event captured on the click of a View component (our text boxes). We will need to use VrButton once again.

First, let’s add the VrButton to our import:

import {
AppRegistry,
asset,
Pano,
Text,
View,
VrButton
} from 'react-vr';

Then, in our TextBoxes component, let’s wrap a VrButton components around the text boxes.

This code snippet is a bit long so you can view it here as it has better formatting.

Here’s an example of one:

<VrButton>
<View style={{ margin: 0.1, height: 0.3, backgroundColor: '#CF3C7E'}}>
<Text style={{fontSize: 0.2, textAlign: 'center'}}>{this.props.states.Arizona}
</Text>
</View>
</VrButton>

Next, we have the code to capture and onClick event and call a function.

Let’s think through this logic.

We want to change the panoramic photo on a click of one of the text boxes.

The panoramic photo that is active is controlled by the local state property selectedState in the PanoramicRoadTrip component.

However, the VrButton that we want to capture the onClick event is in a different component called TextBoxes.

So, how can we update selectedState if it’s controlled by a state that’s in a different component than where we are capturing the event?

First, we need to write a function in PanoramicRoadTrip that will update selectedState when called:

export default class PanoramicRoadTrip extends React.Component {
constructor() {
super();
this.state = {selectedState: ""};
}
  stateClicked () {
//add code here
}

//more stuff here
}

In this function, we want to update selectedState depending on which button is clicked.

Therefore, we will pass in a parameter when we call this function that will tell us which VrButton was clicked and we can act accordingly:

stateClicked (selection) {
//add more code here
}

The selection parameter that is passed in will be a number between 1 and 5. That number will identify which text box (with the name of a state) was clicked.

Therefore, we can use a switch statement to update the selectedState according to the value of the selection parameter:

stateClicked (selection) {
let newState;
switch(selection) {
case 1:
newState = "Arizona";
break;
case 2:
newState = "New Hampshire";
break;
case 3:
newState = "California";
break;
case 4:
newState = "Hawaii";
break;
case 5:
newState = "Texas";
break;
}
console.log(newState); //log the result
this.setState({ selectedState: newState});
}

Cool! Now, in order to be able to call this function on the click of our VrButtons in the TextBoxes component, we pass it down to the TextBoxes component as a prop:

//in PanoramicRoadTrip component
<TextBoxes 
stateClicked={this.stateClicked.bind(this)}
states={states}
/>

Now, our VrButtons can call this function by doing:

//in TextBoxes component
<VrButton onClick={this.props.stateClicked}>

We need to make a slight change to this. We want to pass in a parameter as stateClicked will update the selectedState depending on what’s passed in.

To pass a parameter, we can do this for all of our VrButtons:

<VrButton onClick={() => this.props.stateClicked(1)}>
//...
<VrButton onClick={() => this.props.stateClicked(2)}>
//...
<VrButton onClick={() => this.props.stateClicked(3)}>
//...
<VrButton onClick={() => this.props.stateClicked(4)}>
//...
<VrButton onClick={() => this.props.stateClicked(5)}>

To recap:

  • We have written a function called stateClicked that updates the selectedState property of the local state in the PanoramicRoadTrip component based on an incoming parameter.
  • selectedState controls what panoramic is being displayed in our app.
  • The stateClicked function has to be in the PanoramicRoadTrip component in order to update the selectedState since it is a property in the local state of PanoramicRoadTrip.
  • We want to call the stateClicked function from our TextBoxes component that contains VrButtons that can capture when the text boxes (containing the names of different states) are clicked.
  • To make this possible, we pass down the stateClicked function as a prop.
  • The text boxes in the TextBoxes component call the stateClicked function and passes a number so that the selectedState can be updated accordingly.
  • Now, the click of our text boxes should change the selectedState property of the local state of PanoramicRoadTrip which will ultimately change the panoramic photo that is displayed.

Let’s go to our local host, refresh, and test this out.

Recall, the initial panoramic photo is randomly selected by our componentDidMount lifecycle hook.

As we click the text boxes, we can see that the code is working as our selections are being logged in the console and our panoramic photos are being updated.

Occasionally, I got the following error:

Error: WebGL warning: drawArrays: This operation requires zeroing texture data. This is slow.
Error: WebGL warning: drawArrays: Active texture 0 for target 0x0de1 is 'incomplete', and will be rendered as RGBA(0,0,0,1), as per the GLES 2.0.24 $3.8.2: The dimensions of `level_base` are not all positive.

Essentially, it sometimes WebGL fails to process the updated panoramic. In most cases, however, it works just fine. We won’t go into detail on resolving this at the moment.

Final Code

Code for this chapter is available on GitHub.

Concluding Thoughts

In this chapter, there may have been some parts that seemed trivial to go over since they work exactly like standard React. However, that is the beauty of working with React VR. We are able to make VR applications without reinventing the wheel.

The main differences for the use of components in React VR (as opposed to standard React) are that we have to implement the layout using Flexbox and make use of React VR predefined components (like VrButton) in order to handle events.

All in all, I hope this was an exciting way to explore more of React VR. In the chapters that follow, we will begin to explore even further and do some projects together that can have a major impact in the real world.

Chapter 3

Chapter 3 is now available.

Support the Author

If you would like to support me as I write this book, you can purchase the book here.

The book is published through a platform called LeanPub which allows me to update my book as it progresses. Each time a chapter is added, you will be notified via email. The book will be free to read on Medium, however, purchasing it through LeanPub allows you to download the ebook as a PDF, EPUB, or MOBI file and helps support me financially.

Additionally, I have created a special package that will provide you with a secret link to a Discord server where you will be able to help influence how I write this book.

So go ahead and purchase this book on LeanPub if you would be so kind.


Cheers,
Mike Mangialardi
Founder of Coding Artist