Categories
Technically Speaking

Using GitHub with Expo and Vanilla React Native

Motivation

One of the major disadvantages of making use of Expo is when you have to stop using it – when you come across a missing feature in Expo. The only option left is to eject from the Expo workflow and move to a vanilla react-native stack. Any SDKs you borrowed from Expo can be added using ExpoKit. This immediately sounds like a lot of work and we will discuss about a workflow to integrate both Expo and react-native using GitHub.

About the Project

I am writing this while I am in the process of adapting one of my projects to this new workflow – to say the least, I am learning as I am writing; I am writing as I am learning. This would serve as a personal reference as well while sharing my process with other fellow developers so that they can run where I, crawled.

The project started as a test project but quickly evolved into a financially backed contract. I had not integrated GitHub to the initial project either. What I had was two separate folders. One for the react-native workflow and one for the Expo workflow. Modifications that had a native module part was done in the react-native distribution while using Expo for the UI/ UX modifications and other logic that did not require the custom modules to function. The custom module I wanted to use was react-native-nfc-manager – Expo does not support NFC features as of now.

Expo is a tool at Orpheus that we can not live without. Due to this, we have a bunch of other tutorials that delve into great depths about Expo like the implementation of material design in Expo-based apps.

Using expo eject

A feature introduced in SDK 34 upwards is the ability to eject to what Expo terms a bare workflow. Initially you could only eject to an ExpoKit workflow. Personally, not having used this workflow, I will refrain from commenting on its functionality. But seeing that the folks at Expo are phasing it out and recommending new users eject to bare workflow, I would say that ExpoKit was not successful at its job. What happens to any Expo-based APIs and libraries? The process of moving to the bare workflow will also move the Expo libraries already in use. This is an automatic process.

The beautiful thing with the new bare workflow environment is that it allows you to use the Expo client as long as Native code is restricted from running. Expo provides an API call to detect if the app is running in an Expo mobile client or as a vanilla app.

To eject, simply run,

expo eject
A screenshot showing the manual steps of the eject command used on a GitHub repo project
A screenshot showing the manual steps of the eject command

Do not forget to select “Bare” from the options that come up.

To run the project as an Expo app, simply run –

expo start

Adding native plugins

The next logical step is to add a plugin that is based on native code. In other words, a plugin that would not be able to be added in a managed Expo environment.

The plugin we will use to test this is react-native-nfc-manager plugin. To add this plugin, we use the yarn add command as shown below:

yarn add react-native-nfc-manager --save

To run the app as a vanilla React Native app on a mobile connected via USB, simply execute the following command –

yarn android

Committing to GitHub

Another question that would arise at this point of the process is what folders should be committed to GitHub. The easiest method is to use the gitignore.io online service. This website allows you to select your technology stack to produce a gitignore file. For your easiness, we have already selected and produced a .gitignore file for use on Windows or macOS stacks: https://www.gitignore.io/api/macos,windows,reactnative

The most significant change is that the certain files from android and ios folders (that were made during the eject process) are also chosen to be synced. Commits will exclude build-related files and folders. These files are auto-generated from the source.

Cloning from GitHub

After cloning the repository to a local folder, we need to install the libraries and instantiate Expo (basically, re-creating the node_modules folder) . To do this, you will only require one command:

npm install

Library and script downloads will take some time. After that, we can run it on Expo using;

expo start

Or if we want to check native code and run vanilla React Native, simply run;

yarn android
yarn ios

Sometimes the react-native builder fails to recognize the Android SDK directory. In that case you can set an environment variable pointing to the directory (command shown for Windows):

set ANDROID_HOME=C:\Users\<UserName>\AppData\Local\Android\sdk

The placeholder <UserName> should be replaced with the user’s Windows profile directory name.

We do not have to perform expo eject as our commits already contain an ‘ejected’ work space.

This concludes the Technically Speaking post for today. Hope you learnt something from the post!

Categories
Technically Speaking

React Native Apps styled with Material Design

React Native is the development platform if you are a startup and thinking about developing for both iOS and Android. Apart from containing a ton of source material and community support, development happens in JavaScript. JavaScript is a language that is easy to grasp. Developers are quite likely to have come across JavaScript at least once in their lives. Facebook is its the main contributor and initiator.

Orpheus Digital recently moved from Cordova to React Native. Cordova basically serves web pages in an embedded browser. This has serious performance bottle-necks, specially on budget or mid-range devices. However, Cordova had been around for a longer time therefore the community was larger and more varied. This strong point was being exhausted slowly as React Native was maturing and collecting a strong community.

The strong community resulted in intricate tool kits to make development easier. One of these tools is Expo. We at Orpheus Digital are fans of this tool. This toolkit makes coding production-ready mobile apps a breeze. It takes care of all the mundane tasks and provides infinitely helpful extras like OTA debugging. Code-wise there is not much that differs from vanilla React Native development.

StoreBoss is an app based on this stack that we created. The first app we made using this stack is also StoreBoss. The link #ReactNative will get you to the other articles we have regarding this mobile development stack.

Let’s assume that you have already set up React Native and Expo (seemingly straightforward process that is provided in their respective websites). We will now move onto the material design framework that we, at Orpheus Digital, also use!

React Native Paper

This is the Material Design framework we will be using. Installing this framework is as straightforward as it can get:

yarn add react-native-paper

If you are not using Expo, you would also have to run,

yarn add react-native-vector-icons
react-native link react-native-vector-icons

This adds the library to our project. Now we will use it in our code to render some Material Designed UI elements.

The React Native Code

Startup Code

We like to isolate the starter code from the actual app. So we will have have two JS files: one named App.js which will contain our starter code and another called MainScreen.js (in a folder called src) which will contain our first actual UI.

/*App.js*/
import * as React from 'react';
import { Platform, StatusBar } from 'react-native';
import { DefaultTheme, Provider as PaperProvider } from 'react-native-paper';
import MainScreen from './src/MainScreen';

These import statements all reflect the aforementioned structure of our app. PaperProvider is the root component that our Main component should be wrapped under for the theme to work.

We will also look into defining our own colors for the app, hence the import statement for DefaultTheme.

/*App.js*/
const theme = {
  ...DefaultTheme,
  roundness: 2,
  colors: {
    ...DefaultTheme.colors,
    primary: '#3498db',
    accent: '#f1c40f',
  },
};

The ellipsis (triple dot notation) allows you to only modify the parameters of the theme that you want to while keeping the other parameters unchanged. We have defined our own roundness parameter, and primary & accent colors.

Next, we will code our Main component.

/*App.js*/
export default function Main() {
  return (
    <PaperProvider theme={theme}>
		<StatusBar barStyle={Platform.OS === 'ios' ? "dark-content": "light-content"} />
		<MainScreen />
    </PaperProvider>
  );
}

We specify the custom theme we created earlier as a parameter for the PaperProvider. The StatusBar element refers to the area of the UI where the time, battery status…etc are shown. We are using a neat trick to make the content area darker or lighter based on the OS for improved legibility using the Platform React Native API.

MainScreen Code

Next we will layout our Appbars and buttons for our main UI screen.

/*MainScreen.js*/
import React from 'react';
import { Text, View, Alert } from 'react-native';
import { Button, Appbar } from 'react-native-paper';

The good thing about the Paper framework is that the components need to be imported as required. This is a good thing for two different reasons:

  1. Decreases overhead – you import only what you need for that view
  2. Improves flexibility – maybe you want to use a button from another library in just one screen
/*MainScreen.js*/
export default class MainSceen extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
        }
    }
	
	render () {
		return ([
		  (
			<Appbar.Header key="1">
			  <Appbar.Content
				title={<Text>Hello</Text>}
				subtitle={<Text>Subtitle</Text>}
			  />
			  <Appbar.Action icon="filter" onPress={() => {
				Alert.alert("Alert", "You pressed on the filter button!");
			  }}/>
			</Appbar.Header>
		  ),
		  (
			<View key="2" style={{margin: 10}}>
				<Button icon="camera" mode="contained" onPress={() => Alert.alert("Alert", "You pressed on the contained button!")}>
					Press me
				</Button>
				<Button icon="camera" mode="outlined" onPress={() => Alert.alert("Alert", "You pressed on the outlined button!")} style={{marginTop: 10}}>
					Press me
				</Button>
			</View>
		  )
		]);

	}
}

This is our entire MainScreen.js A relatively new feature in React Native is the ability to use a key parameter in the return statement of the render() function to string together different components without having to wrap the components in a parent element. The individual components are instead provided as an array.

Also note how the Appbar component is consumed.

Now, the project can be run using the start command

yarn start

The output app will look similar to this on the two different platforms. The main reason for our liking of the React Native Paper library when opting for a material design interface is how the styling adapts to more of an iOS-like theme when the app is run on iOS.

The interaction with the buttons reveals the ripple effects.

A screenshot from the React Native project running on an Android environment
Our test app running on Android
A screenshot from the React Native project running on an iOS environment
Our test app running on iOS

Thus, we conclude the Technically Speaking post for today. The project can be accessed from our GitHub repository