Whether you want to experiment with developing a mobile app or have a business idea in mind, kicking off mobile development with React-Native is a great idea, and it’s especially an obvious choice if you are already familiar with React.

In this series, we’ll cover the basics of React-Native development, compare some ideas with React, and develop a game together. By the end of this tutorial, you’ll become confident with using the built-in components, styling, storing persisting data, animating the UI and many more.

React-Native-Guide-Application-Screen

If you want to check out the full sourcecode, here's the GitHub repo.

This series is recommended for developers already familiar with React, so we won’t take too much time explaining basic React concepts.

In Part I. of this series we'll discuss the following:

  • React-Native vs real-native: what’s the deal?
    • What is React-Native, who is behind it?
    • Why would you want to develop in React-Native?
    • Key differences and similarities between RN and native apps
    • A few words about real-time reload over recompiling
    • How does RN compile and work in the background?
  • What’s Expo?
    • The core concept behind Expo: extending React-Native features with pre-written native features
    • The brief history of how it became the main interface for developing React-Native apps
    • Pros and cons of using Expo over developing purely in React-Native
  • Differences and similarities between React and React-Native:
    • States and props
    • Flexbox (how it works in React-Native)
    • Components & most important pre-written components
  • Initializing the environment:
    • Installing the CLI, creating the project
    • Exploring directory structure
    • Assets (icons, fonts, music, sfx)


React-Native vs real-native: what’s the deal?

You may look down on hybrid apps because of their poor performance in the past (I’m looking at you Ionic!), but you can forget them for now.

In the background, React-Native uses the same native building blocks as you would use while developing native apps with Swift, Java or Kotlin. The only difference is that you put these building blocks together with JavaScript.

But if it’s just a simple API wrapper, why do developers love it, then?

React-Native’s real power comes from giving you a load of features that improve the developer experience, like Live Reload that reloads the app in a few seconds when saving, or Hot Reloading that injects code changes without reloading the app and losing your state.

Here’s a video that compares these two.


What’s Expo?

As you may have already noticed, the React-Native documentation features Expo CLI as the default toolchain to get started. Let’s take a look at what’s Expo, where does it come from, and why is there a 3rd party in the official documentation.

Expo is an SDK that started as an unofficial toolkit, but then it grew into a much bigger project with features like OTA app updates (bypassing the long App Store review times), social authentication, camera access, push notifications and many more services out of the box, for totally free!

They also have an online playground named Snacks where you can try out other people’s code online, or work on bite-sized projects without the need of creating a project in the CLI.

The core concept behind Expo is to extend React-Native with pre-written components like the ones mentioned above. Expo has awesome documentation with an exhaustingly long list of APIs in the sidebar, be sure to check it out!

However, Expo also has its downsides: your app will have a considerable size when you build it (about 20-30MB .apk for a Hello World project) because it has all of these features built-in, not only the ones that you use; and at this time, you can’t explicitly write or use native Swift/Kotlin code.

Since we aren’t aiming production nor planning to write native code in our project as we’re only building an example project, Expo is the fastest way to start off, thus we’re going with it.

(However, if you want to, you can always detach your project from Expo.)


Does React-Native have a different approach for the same concepts as React?

In short: no.

For example, states and props work the same way, components have the same underlying idea to them as in React, and you can even access React APIs (like the Context API) within React-Native. However, some things couldn’t be implemented the same way as in React, simply because web development’s logic differs from mobile.

For example, flexbox works the same way in CSS with a few exceptions: the flex-direction is defaulting to column instead of row, and the flex only supports a single number as a parameter. Also, it’s the default method to build UIs. If it isn’t already familiar for you, consider practicing the use of flexbox: Flexbox Froggy is a cool game that you should try before moving on with the tutorial.

Since you aren’t writing for the web, you cannot use default HTML tags like div or img - you’ll need native UI components.

Please keep in mind that the default components may look and behave differently on different platforms, so you should always test them on all platforms before releasing something. (Oh, and negative margins don’t work on Android)

But what are the building blocks of the UI if not HTML elements?

There are plenty of useful pre-written components that React-Native provides us. For example, instead of <div>s, you use <View>s, for displaying texts, you use <Text>, for buttons, you use <Button>, and so on. Please be sure to check out the official documentation that highlights the most important components (and the full list is always available from the sidebar) before moving on.


But what are we building, exactly?

Good question. We are building a fun minigame I call “ColorBlinder”. The main game screen is pretty simple: it’s built up from a few tiles that are colored the same, except one. The player’s task is to tap the differing tile as fast as possible.

React-Native-Guide-Application-Screen-1

Some mockups I made before starting the development, just to illustrate the main idea. We’ll use these illustrations along the course when building components.


Let’s just start developing already! a.k.a. setting up our Development Environment

Okay, okay, geez, don’t be so impatient! We’ll get to it soon enough, but first, we’ll need some tools to kick off the development. Make sure that you have Node.js installed, and install the Expo CLI:

npm i -g expo-cli

Then let’s init an empty project. I’ll call it colorblinder as this is the name of the game we’ll work on along the series, but you can call it whatever you want.

expo init colorblinder

## choose `empty` template for this project
## choose `managed` workflow
## write in `ColorBlinder`
## if it asks, use yarn to install dependencies. (If you don’t have it, [be sure to check it out](https://yarnpkg.com/), it’s a fast alternative to npm)

cd colorblinder
npm start ## or yarn start if you have yarn, or expo start, whichever you prefer

This command will start the development server with an empty project for you, and open a new Chrome tab with the Expo DevTools. You can use a simulator or a device with Expo Client installed, whichever you prefer.

If you want to check out the full source code in one piece, check out the GitHub repo.


Project Structuring our React-Native Game

First, let’s explore the directory structure of our new project.

├── App.js
├── app.json
├── assets
│   ├── icon.png
│   └── splash.png
└── package.json
# a few more files that we don’t care about yet

The structure may seem simple, but just to make sure that it all makes sense, we’ll look through it.

First, let’s explore the app.json. It’s a configuration file for Expo: it contains the SDK version, name, logo/splash screen directions, platforms, GitHub URL, and a lot more. Explore it in details from the documentation.

If you want to develop the game on your own, download the assets and copy-paste it into your assets directory. Make sure that you are overwriting icon.png and splash.png! The sound effects originate from here, and we’ll use music made by Komiku - be sure to check them out and donate for their work if possible, they deserve it.

After you pasted in the assets and open the app, you may notice that the sizing of the splash screen is a bit off, so before we start initializing our home screen, we should fix that. In the app.json under the splash property, set the backgroundColor to #0a0a0a.

(If you don’t see it yet, restart the packager and/or the client).


Let’s Start Coding!

As you may have seen, we’ll have a few different screens (two, to be exact), so we are going to need a router to navigate between them. Expo’s documentation has a pretty good explanation on why you may need a router if you aren’t familiar with the idea of using routers already. We are going to use react-navigation, so I suggest to check out their Getting Started guide.

Add react-navigation as a dependency to the project:

yarn add react-navigation
## if you don’t have yarn: npm install react-navigation

Create a components directory for our components that we’ll build (like the header or the grid), and a screens directory for the screens we’ll compose (the Home and the Game screen exactly). Make sure that both of the directories are in the root of the project, and create Home.js in the screens directory. Just to make sure that it renders something, copy-paste this into it:

import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default class Home extends Component {
 render() {
   return (
     <View style={styles.container}>
       <Text>ColorBlinder - Home screen!</Text>
     </View>
   );
 }
}

const styles = StyleSheet.create({
 container: {
   flex: 1,
   backgroundColor: '#fff',
   alignItems: 'center',
   justifyContent: 'center',
 },
});

Notice that you are extending the React.Component class, so nothing new there. Instead of divs, you are using <View>s that are imported from the react-native package, and to show some text to the user, you use a <Text> tag.

Also, the StyleSheet on the bottom of the file may look weird: it’s a React-Native specific API. It’s basically an abstraction for CSS: you can create new styles in the object and name them anything you’d like, and you can use basic CSS properties (just camelCased) to define properties.

You can use them in your JSX simply by putting the name of the style in the style={} prop. (If you want to separate the JSX and the styling, you can, but for now, we’ll have them in the same file - we will move the StyleSheet to a different file later, though!)


Initializing the Routing

Now that Home.js is rendering something, let’s initialize the routing in the App.js:

import { createStackNavigator, createAppContainer } from "react-navigation";
import Home from './screens/Home';

const AppNavigator = createStackNavigator({
 Home: {
   screen: Home
 }
});

export default createAppContainer(AppNavigator);

We are using react-navigation’s createStackNavigator: it initializes a new stack navigator that returns a React component that we can render - thus we can export it from App.js and except it to work.

When you run the code, you’ll see something like this:

You can see that there’s an (empty) navigation bar on the top of the screen: we definitely don’t want it to be visible as it would make the game look terrible, so in the App.js, let’s spice up our stack navigator with some properties:

const AppNavigator = createStackNavigator(
 {
   Home: {
     screen: Home
   }
 },
 {
   initialRouteName: "Home",
   headerMode: "none",
 }
);

The top navigation bar will now be hidden.


Using Custom Fonts

The Expo documentation’s guide gives you a straightforward idea on how to use custom fonts in your app, but we will need some major changes in our app structure to be able to integrate them into the project since we are using a navigator.

As you can see, you need to render a different component while you are loading the font (the splash screen would be perfect!), so first, rewrite your App.js as the following:

import React, { Component } from 'react'
import { AppLoading, Font } from 'expo';
import Routes from './screens/Routes'

class App extends Component {
 state = {
   isFontLoaded: false
 }

 async componentDidMount() {
   await Font.loadAsync({
     'dogbyte': require('./assets/fonts/dogbyte.otf'),
   });
   this.setState({ isFontLoaded: true })
 }

 render() {
   if(!this.state.isFontLoaded) {
     return <AppLoading />
   } else {
     return <Routes />
   }
 }
}

export default App;

We are asynchronously importing the font dogbyte. The state has an isFontLoaded property that will be true when the font is loaded. While it’s false (or in other words, while the font is not loaded), it will render the <AppLoading /> component that comes from the Expo SDK. This component shows the splash screen of the app when rendered.

When the this.state.isFontLoaded is true (when the font is loaded), it will render the Routes component, that is undefined as of now, so let’s quickly create a file under screens named Routes.js and copy-paste our previous navigator code into it:

import { createStackNavigator, createAppContainer } from "react-navigation";
import Home from "./Home";

const StackNavigator = createStackNavigator(
 {
   Home: {
     screen: Home
   }
 },
 {
   initialRouteName: "Home",
   headerMode: "none"
 }
);

export default createAppContainer(StackNavigator);

Prepare for the next part of our React-Native Guide!

At this point, we have basic navigation initialized in our app and can use our custom font. It’s time to call it a day, pat yourself on the back for making it this far into your journey and have a rest.

In the next session, we’ll build the home screen of the app!

colorblinder-react-native-homescreen

You can read the next episode here: A Definitive React-Native Guide for React Developers: Part II.

If you weren’t following along or you got stuck somewhere, you can access the code that’s written at this point here.