13.2 Pressable and Production Builds

# Touching and Tapping Components

Another difference between React and React Native is how interaction with the user is handled. In the browser, developers are used to using the mouse events, like click, mouseover, and mouseout.

On a mobile device the user is using their fingers for navigation and interaction. JavaScript does also have the TouchEvents and the PointerEvents but these will all fallback to the Mouse events like click when running in a mobile browser.

When it comes to native mobile apps, and native components we do not have click as an event. Instead we have the onPress, onPressIn, onPressOut, and onLongPress events.

By default, certain native components, like buttons, support listeners for those Press events. However, this is not the case for all elements. <Text> and <View>, your two most common components do not support the PressEvents.

# TouchableOpacity, TouchableWithoutFeedback, TouchableHighlight

To add support for the PressEvents, we need to wrap other components inside something that can be pressed.

Until recently, we could make things touchable or pressable by wrapping our components inside of one of three components.

All three support the PressEvents. The difference is just in the visual feedback given to the user when the touch the element.

# Pressable

In more recent versions of React Native there is a new component called Pressable which is aimed at replacing the other three.

The <Pressable> component wraps your components to add the support for the PressEvent listeners. To change the visual feedback to the user, we use the style prop inside it. We give it a function that will pass in a Boolean that indicates whether or not the component is currently being pressed.

Here is an example from the reference (opens new window):

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

const App = () => {
  const [timesPressed, setTimesPressed] = useState(0);

  let textLog = '';
  if (timesPressed > 1) {
    textLog = timesPressed + 'x onPress';
  } else if (timesPressed > 0) {
    textLog = 'onPress';
  }

  return (
    <View style={styles.container}>
      <Pressable
        onPress={() => {
          setTimesPressed((current) => current + 1);
        }}
        style={({ pressed }) => [
          {
            backgroundColor: pressed
              ? 'rgb(210, 230, 255)'
              : 'white'
          },
          styles.wrapperCustom
        ]}>
        {({ pressed }) => (
          <Text style={styles.text}>
            {pressed ? 'Pressed!' : 'Press Me'}
          </Text>
        )}
      </Pressable>
      <View style={styles.logBox}>
        <Text testID="pressable_press_console">{textLog}</Text>
      </View>
    </View>
  );

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
  },
  text: {
    fontSize: 16
  },
  wrapperCustom: {
    borderRadius: 8,
    padding: 6
  },
  logBox: {
    padding: 20,
    margin: 10,
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: '#f0f0f0',
    backgroundColor: '#f9f9f9'
  }
});

export default App;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

# Production Builds

Expo makes it very easy for developers to build and test their apps. A simple yarn start on the command line begins the Metro build and gives you a QR code to scan with any phone that has the Expo Go client app installed.

Hot reloading is included with Expo which means you can edit and test continually.

But what about your client?

What about testing when your dev server is not running?

What about testing when you are away from your wi-fi network?

To answer these concerns we have a few options.

# Expo publish

With the Expo CLI we can create a hosted version of our React Native App. This will still be using the Expo app as the delivery mechanism. Your client will still need to install the Expo app on their phone. However, it will create a URL that you can share with your client or other developers for testing. The URL, once opened in a browser will have the QR code that gets used by the Expo Go app to load the currently published version of your app.

You must first create an account with Expo (opens new window). Then you can use the CLI to create this production version.

You can find out if you are logged in from the CLI by using the expo whoami command. If not logged in then you can use the expo login command.

expo whoami
expo login
expo publish
1
2
3

Here is the Expo CLI reference (opens new window)

On the Expo website you will have a page where you can see all the different builds you create. Eg: https://expo.dev/accounts/[your username]/builds

Clicking on one of your listed builds will take you to the details page, where you can download the .aab Android Application Bundle file or .ipa iOS App Store Package file.

iOS Warning

It is important to note that you must have owner rights on your iOS dev account to be able to create your signing certificate and actually create the downloadable .ipa file for iOS.

# From the Metro Dev Server

If you have your Metro bundler running through expo start then you can visit your Metro webpage http://localhost:19002 and click on the Publish or republish project link in the left hand menu.

This will let you do the same thing as with the expo publish command.

It will open up the Expo.dev service page for your app. You will need to be logged in to the Expo website to do the publishing. This page will have a QR code that can be scanned with a phone, which will need the Expo Go app installed. That phone will be able to run the published version of the app at any time. You won't have to have your Metro Dev server running on your computer.

For iOS, there is a security restriction. To load the published app via Expo Go, the user must be logged in to the Expo account that was used to build the app. If you are logged in to the Expo.dev website then you will have a page that you can access from anywhere to demo your published app.

If your intention is to share the app with a client, this leaves us with the following options:

  • Create an account for your client and log in to that account on your computer before you publish the app to Expo.dev.
  • Give your client your Expo credentials so that they can log in to the website and then open the app on their phone.

# Expo Build

If you want to create the binaries locally from your Expo project you can also run the expo build command.

expo build:android
expo build:ios
1
2

It has the same limitations for iOS. You need to have the owner rights on the iOS account.

# EAS-CLI

A new solution for publishing and creating your mobile binaries has been created with a tool called Expo Application Services.

EXPO and EAS is designed to run in a manner similar to Cordova and PhoneGap. One is the free public tool. The other is aimed at enterprise clients who need more support and more robust tools. Luckily EAS comes with a free level account. Great for students and independent developers.

It uses the node package eas-cli. You start by installing it globally on your computer using npm.

npm install -g eas-cli
1

Here is an article (opens new window) about how EAS works and what it does.

It also has the login and whoami commands.

eas whoami
eas login
1
2

With EAS you will be creating the binaries for your project without the same limitations that expo build (opens new window) had.

It still has the restriction about iOS and needed the distribution p12 certificate, which only the iOS dev account owner can create.

# Expo Eject

The expo publish command creates that link for the demo version of your app. Both the expo and eas build commands will create binaries (only if you have the distribution certificate for iOS).

One of the things that makes Expo a great development tool is the fact that is skips having the ios and android folders with the real mobile app project. The downside is that you don't have the mobile app project to open inside of XCode or Android Studio. This means that you don't have access to those tools to add native modules or push to devices without signed certificates.

That is why we have the expo eject command.

WARNING

This command cannot be undone. When the command runs it will put your project back to the same state it would be right after running expo init

Before running this command, be sure to git add -A and git commit all your changes.

Then create a new branch where you will do the ejecting.

git checkout -b ejected
expo eject
1
2

You will get prompted to enter a package name for Android and bundle identifier for iOS. Use the same name in reverse domain name format. Eg: com.algonquincollege.myusername.myapp Just like for Cordova.

This will create the /ios and /android folders and set up your projects as if you had started with npx react-native init MyProject.

Cocoapods must be installed for this to work. See week 11.1 (opens new window) for the notes on the non-expo setup.

It will take a while but you will have your React Native app along with the ios and android versions that can be opened in XCode or Android Studio.

There may be a few native tools missing so, after the eject command is done running, run this:

npx @react-native-community/cli doctor
1

It will review the tools that you have installed and tell you about any issues to fix. Then it gives you the options to fix the problems. Sometimes it can be easier to manual fix the problems by doing the updates and installs through XCode, npm, or Android Studio SDK manager.

Then, to build your app you can use the command:

npx react-native start
npx react-native run-ios
npx react-native run-android
1
2
3

The start command can be run first to build the JS part of the project and start the Metro bundler.

Both the run commands will build your app and try to launch it in the emulator/simulator.

It is worth noting that if you have a JDK version 17 installed, it will not like your React Native project and you will get lots of Gradle build errors.

For Android, the Emulator should be running first or you can have a physical device connected via USB. After the run command is done you will have your apk file that you can install and run on a phone. For android, look inside /android/app/outputs/apk/debug/ for the app-debug.apk file. This is the file that you can install and run just like you would for Cordova.

For iOS there may be dependencies that are not linked to the project. You can fix this by running:

cd ios
pod install
1
2

To Open and Run the iOS version from XCode, open the /ios/[APP NAME].xcworkspace file in XCode and then you can run the app from there. This can install and launch your app on any attached and signed device.

NOTE: Not the .xcodeproj file but the .xcworkspace file.

Remember to select the project in the workspace, go to the Signing & Capabilities tab, select the Algonquin College (Media and Design) team from the dropdown list and have Automatically manage signing checked.

The run button in XCode can build and launch the App on your device. If you change your JS code then use the npx react-native start command to update the JS part of the project before doing another build and run from XCode.

Sometimes additional work has to be done removing things that were added with Expo. Honestly, it is often easier to create a new project with npx react-native init MyProject and then copy over your JS files and assets into the new project, than to Eject from expo and fix things.

# Firebase App Distribution

Another way to deliver test versions of your app to your client is through Firebase.

Firebase has a section in the control panel called Android. It lets you upload the .ipa, .apk or .aab files, create a list of allowed users (by email address), and then distribute those files via an email.

The person receiving the email will get BOTH the binary file for the app, plus a signed certificate from Firebase that lets the person run your mobile app.

For iOS it means being able to provide clients with beta versions of your app without dealing with the App Store.

For both iOS and Android it means your client feels safe because they are getting to install a signed application on their device.

Every time you do an updated version upload to Firebase, the users in the list will automatically be sent an email with a link to the updated app.

Obviously this doesn't work for general distribution to the public because you need an email address for each person who will download the app. However, it might work for something like an internal app for a small company that had fewer than 100 employees.

Last Updated: : 12/5/2021, 7:49:53 PM