8 min read
So, for my next project, I’ve decided to build a mobile app.
The (tentative) name of the app is Keep UP. It is a Personal Relationship Management tool to helps you keep up with friends & family.
Here’s how it is meant to work:
This article series will cover the process I went through to build the application.
In Part 1, I will show how I set up a new React Native project using Expo, add multiple screens and add a bottom bar navigation to switch screens.
Currently, there’s several ways to build mobile apps. There’s pure native development using Java or Kotlin for Android and Objective-C or Swift for iOS. There’s also several hybrid tools such as React Native, Ionic and Flutter.
After some consideration, I decided to go with React Native because:
In order to move faster, I decided to use Expo to build the application.
To install Expo, I followed the instructions on the website, but faced a few issues
sudo
(muahahahaha).To initialize a project with expo, we have to run the command: expo init my-project
Doing this, I was faced with a decision:
expo init
Decided to go with blank
because:
After all had been initialized, I was left with a pretty nice directory structure, and an App.js
file at the root of the project with this:
// App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Testing out the program was pretty dope using Expo.
All I had to to was cd
into the directory and run npm start
.
I got a really nice dev tools page, and I could view the program from my Android phone by downloading the Expo app and scanning the QR code.
The next thing I felt I needed to figure out was Navigation.
To add navigation, I did some googling and found the react-navigation
library. To install, I ran expo install react-native-gesture-handler react-native-reanimated
.
Following the direction in the documentation here, I added the navigation to the default code in App.js
to leave me with this:
// App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
class HomeScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
const AppNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
},
});
const AppContainer = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
I’m a fan of Material Design and want to follow it (as much as I can) for this application.
Thankfully, since Material design is so popular, there is a great package to help with getting it right.
From my research, the most popular (by far) is React Native Paper.
To add it to the project, I ran expo install react-native-paper
and then reading further down the Getting Started documentation, I also installed babel-plugin-optional-require
to reduce my bundle size when building for production using npm install --save-dev babel-plugin-optional-require
.
After that, I modified babel.config.js
(found at the root of the project) to look like this:
// babel.config.js
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
env: {
production: {
plugins: ['react-native-paper/babel'],
},
},
};
};
Now, in App.js
, we’ll import react-native-paper
and add it to the render:
// App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { Provider as PaperProvider } from 'react-native-paper';
// Other code follows as usual...
export default class App extends React.Component {
render() {
return (
<PaperProvider>
<AppContainer />
</PaperProvider>
);
}
}
At this point, I feel like we should structure the code better, so we’ll move the home component into a different file and import:
Let’s create a folder called views and a file name home.js
inside it.
Then we’ll put this in ./views/home.js
:
// ./views/home.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export class HomeScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
}
Then we refactor App.js
to this:
import React from 'react';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { Provider as PaperProvider } from 'react-native-paper';
import { HomeScreen } from './views/home';
const AppNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
},
});
const AppContainer = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return (
<PaperProvider>
<AppContainer />
</PaperProvider>
);
}
}
Now, I want to add another screen to show a list of saved contacts.
I’ll create a new file ./views/contacts.js
and mostly duplicate the content from ./views/home.js
:
// ./views/contacts.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export class ContactsScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Open up ./views/contacts.js to edit this screen!</Text>
</View>
);
}
}
Then we update our App.js
to look like this:
// App.js
import React from 'react';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { Provider as PaperProvider } from 'react-native-paper';
import { HomeScreen } from './views/home';
import { ContactsScreen } from './views/contacts';
const AppNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
},
Contacts: {
screen: ContactsScreen,
},
});
const AppContainer = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return (
<PaperProvider>
<AppContainer />
</PaperProvider>
);
}
}
While we have two screens, we currently have no way of switching between them
Earlier, I mentioned that I did not want to use tabs for navigation. Well, my chosen navigation element is a bottom bar.
Thankfully, there is good documentation on creating a material bottom bar navigation for react-navigation
. Also, it uses react-native-paper
so.. YAY!.
To do this, I first had to install the appropriate library: npm install --save react-navigation-material-bottom-tabs
.
Then, I updated App.js
to this:
import React from 'react';
import { createAppContainer } from 'react-navigation';
import { Provider as PaperProvider } from 'react-native-paper';
import { HomeScreen } from './views/home';
import { ContactsScreen } from './views/contacts';
import Icon from 'react-native-vector-icons/FontAwesome';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
const AppNavigator = createMaterialBottomTabNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<Icon name="home" size={20} color={tintColor} />
)
}
},
Contacts: {
screen: ContactsScreen,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<Icon name="users" size={20} color={tintColor} />
)
}
},
},
{
initialRouteName: 'Home',
activeColor: '#000000',
inactiveColor: 'rgba(0, 0, 0, 0.54);',
barStyle: { backgroundColor: '#FFEB3B' },
}
);
const AppContainer = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return (
<PaperProvider>
<AppContainer />
</PaperProvider>
);
}
}
So, I’ve created the “skeleton” for the application, next I’ll have to figure out a storage system and then begin to flesh out the screens.
If you have any thoughts or suggestions, let me know in the comments. Till next time ✌🏾.
Part 1: Setting up using React Native and Expo Part 2: Ditching Expo Part 3: Adding authentication with firebase In the first part of this series...
3 min read
Part 1: Setting up using React Native and Expo Part 2: Ditching Expo Part 3: Adding authentication with firebase Next I am going to add authenticat...
4 min read
Comments