Create a React Native Web App with Hooks, Bells, and Whistles with Expo SDK33 [Part 1]

Earlier today, publically released the long-awaited v33 of their Expo SDK and we’ve got a whole lot of new features to play with. To name just a few, here’s a short list of my favourites.

Expo SDK v33 Features

  • Expo Web
  • React Hooks
  • Typescript
  • Bare Workflow (pick and choose, no Gorilla included)
Build once & deploy to iOS, Android, and desktop web! (image courtesy of

With all those new tools under our belt, this is a great moment to start a small tutorial series to get started with those features as well as a little refresher for Expo / React Native Basics.

[Part 1] ← You are here!
[Part 2] Linting and Redux

I’ve created a repository on GitHub for you as a resource to check the code but I’ll quickly go over the initial steps as well so you can either code along or skip to Tag v0.1 in my repository. Also, this will be a multi-part tutorial so I’ll update this article’s section to include links to the following parts as soon as they are available.

You’ll need Node.js installed (anything equal or higher than v8) and I highly recommend using a versioning system like git to track your work so you can easily revert changes that didn’t work as intended, especially if you don’t follow this guide bit by bit but use it as a general guide on how to set up a new project. I’ll be using npm for installing packages and running my scripts but you might just as well use yarn if that’s more your style.

You can test your app on your own devices if you download Expo Client for Android from the Play Store or for iOS from the App Store.

If you want to test your app locally for iOS, you will need to install Xcode through the Apple App Store. Working on a Windows or Linux machine, you won’t be able to emulate the iOS client (to my knowledge) but you can always install an Android emulator. The Installation Section from the expo documentation got you covered there.


Install the Expo CLI globally by running:

npm install -g expo-cli 

To proceed, you will need to create an Expo account but I think you won’t need a HowTo for that. As soon as you’ve done that, open your terminal (iTerm2 is a good choice if you ask me) and create your new project.

expo init expo-base

This starts the guided project setup. When prompted, pick the blank template from the Managed workflow. That way, you will get a new project with a clean slate and it will be easier to follow along. You will also get to choose a name and slug (based on the project folder). I went with “Expo Base - Starter Kit” for the name and “expo-base” as the slug.

Then cd into your new project and run start to fire up the Expo DevTools.

cd expo-base
npm start

You can either scan the QR code with your testing device or directly start an emulator from the DevTools Web Interface.

From my own experience, the iOS simulator runs a bit sluggish at times. If you run into an error on startup, wait till the emulator is done loading and press the “Run on iOS simulator” button again.

If you want to compare your result or skip this step, feel free to check out my Tag 0.1 - Base Setup on GitHub. If you use this tag as your starting point, keep in mind that you need to install node and expo nonetheless as mentioned at the beginning of this series.

First Steps: Navigation

Well start by setting up a simple 3-page navigation with a Home, Settings and Start page. First, we need to install the react-navigation package as a production dependency.

npm i -save react-navigation

Now open the project in the IDE of your choice and create a new folder called src/ with a nested folder called scenes/. This is where we’re gonna put all “scenes” or “pages” if you like. In this new folder, we start by making a new file called SceneHome.js as a starting point for our app.

I personally prefer to prefix those files with “Scene” for better scanning of open files in my IDE but that’s a personal preference.

// SceneHome.jsimport React from 'react'
import { StyleSheet, Text, View} from "react-native"
const SceneHome = () => {
return (
<View style={styles.container}>
<Text>Hello World!</Text>
<Text>Home Page</Text>
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
export default SceneHome

Now use this template to create two copies called SceneSettings and SceneStart. In those copies rename the const from SceneHome to SceneSettings and SceneStart respectively, pick a different backgroundColor and replace all Text tags with a single new Tag containing a different text, so we can easily see that we navigated to a new scene. I went with the following:

  • Scene Settings // #ccc
  • Scene Start // #ff7100

Next, we’re going to change the App.js in your root directory to show dynamic scenes, based on the current navigation state. First of all, we’re gonna get rid of the styles and View. Then we will import two elements from react-navigation as well as our new scenes.

// App.jsimport React from 'react'
import {
} from 'react-navigation'
import SceneHome from "./src/scenes/SceneHome"
import SceneStart from "./src/scenes/SceneStart"
import SceneSettings from "./src/scenes/SceneSettings"

Now we need to tell our app, what scenes we want to show. To do that, we create a new Navigation component by defining a TabNavigator and handing that to our new app container. The TabNavigator component will hold our Scenes (Home, Settings, Start) and map those to their respective React Components. You can also add an initialRouteName if you don’t want the first tab to be selected by default.

let TabNavigator = createBottomTabNavigator(
Home: SceneHome,
Settings: SceneSettings,
Start: SceneStart,
initialRouteName: "Home"
let Navigation = createAppContainer(TabNavigator)

The last step is to remove the old View tag from the render function and replace it with our Navigation component and we’re done for now.

export default function App() {
return (
<Navigation />

If you’ve kept the emulator open while coding, you might have experienced a few red and error-ridden screens. This is due to the fact that the Expo DevTools are always updating the preview in your connected devices. In some cases, the error screen blocks this automated reloading so either reload manually or restart the simulation from the Expo DevTools, if reloading doesn’t work. If you still run into errors, carefully read the description in the preview. In most cases, the stack trace easily helps you find the problem, be it a small typo or a missing dependency.

Your Preview should now show you a white page with 2 lines of Text reading “Hello World!” and “Home Page” as well as a bottom tab navigation. Clicking on those tabs will change the current scene and if you want to check that our setup really works, change the initialRouteName in our createStackNavigator from “Home” to “Settings” and if you followed my suggestions, you should immediately see a grey page reading “Scene Settings”.

Recap: We’ve created a new Expo / React Native Project and implemented a simple and unstyled tab navigation. Our next steps will be a basic Redux implementation as well as some more useful examples for Navigation and our Redux Store.

If you want to take a look at the current code, go to the tag v0.1.1 - Base Navigation on GitHub. If you had any problems following along, feel free to ask questions in the comments. I’ll try to get back to you as soon as possible.

Next Steps: [Part 2] Linting and Redux

Outlook: Once this series is done, I’ll start writing a series on basic game design principles and how to build simple games for iOS, Android and the web, using Expo and React Native. I’ve also started a series of straightforward tutorials for Redux and React will follow soon. If you want to support me in writing more articles like this or if there is a specific topic you would like to learn more about, feel free to visit my Patreon Site. I’ll post regular updates there as well as some special content and previews of projects I’m working on as a bonus for backers.

I’m a Web / App Developer & father 👨‍👩‍👧 doing freelance and part-time agency work since 2003, 💻 building stuff on the side 🕹 and attending conferences 🎟