Ionic Vs. React Native: Building a WhatsApp UI Clone — Part 2

Hani Bhat
7 min readMar 20, 2020

--

Ionic Vs React Native

For the Ionic Framework tutorial, check out part 1 of this series.

Part 2: React Native

React Native is an open-source cross-platform development library that makes it extremely easy for React.js developers to build native apps for Android and iOS. It supports JSX for creating UI components, and has a handful pre-defined components that you can (and should) use in building your app’s custom components. Those pre-defined components are the only components that are translated into native view elements in the corresponding mobile device platform. Additionally, there are a number of UI libraries you can use on top of React Native to make your development much much easier and simpler; for example, NativeBase and UI Kitten.

Unlike Ionic, React Native renders truly native view elements within the app. The cool thing is that the business logic is written in Javascript/Typescript and runs on Android or iOS. This eliminates the need to learn and develop in different programming languages, like Java or Swift, to build apps for different operating systems.

You will find the complete code of this tutorial in this repository:

Now let’s get started with our project.

Prerequisites

  1. Node.js
  2. Expo CLI

Setup

Open the terminal and navigate into a directory of your choice, then run the following command to create a new blank React Native project:

expo init whatsapp-clone

When prompted, choose the blank (TypeScript) template for this project. After the process completes, the project should be created and ready. Navigate into the newly created directory using the following command:

cd whatsapp-clone

To make things simpler, we will use a couple of tools to help us with the UI; in particular, NativeBase and Moment.js. So let’s start installing those dependencies.

Firstly, install NativeBase:

yarn add native-base --save

Next, you will need to run this command to install the fonts package:

expo install expo-font

Finally, install Moment.js:

npm install moment --save

Now, you can start the dev server to launch the app:

yarn start

The DevTools should open up on your browser automatically. Start the Android emulator and click “a” on your keyboard to run the app on the emulator, or scan the QR code to run it on your mobile device (Expo app is required).

UI Implementation

Open up the project with your favorite IDE. As you can see in the screenshot below, in the main screen of WhatsApp, there is a header with a couple of buttons and four tabs.

WhatsApp’s Header and Tabs

The tab content (displayed under each tab) is rendered only if the corresponding tab is selected. To make our implementation much simpler, let’s get some help from NativeBase components. The Header component can be used of course for the header, including the buttons, and the Tabs component for the tabs and their content. Create the following directory: whatsapp-clone/src/components and create two files inside of it: MyHeader.tsx and MyTabs.tsx. Those two files will be the main components of our app. Now, let’s set up NativeBase in our app and render those components from our main screen. Open up App.tsx and replace its content with the following:

App.tsx

Most of what is happening here is bootstrapping our app and importing NativeBase fonts and icons. The important part is the return statement of render(). Within a Container, we are rendering our previously created components. Right now the screen will display nothing as those components are empty.

Let’s set up our theme colors so that they are ready when we need to use them in our components. Create src/constants/ThemeColors.ts, and add the following:

ThemeColors.ts

This is a very simple way to have your app’s theme colors available from a single source. We can import this object in any component in our project and use the colors without going through the hassle of having to write the hex color values on each style property where it is needed. Now head over to components/MyHeader.tsx and copy and paste the following in its content:

MyHeader.tsx

Basically, we are importing here the necessary components from NativeBase and our theme colors. Then, we are rendering a Header with a couple of Icon-only Buttons on the right-hand side. NativeBase Header has a few useful properties, noShadow, hasTabs and transparent, which we use here to make the header look more like WhatsApp’s, and we set the background color of the header to our primary color from ThemeColors.

Open src/components/MyTabs.tsx and write in it the following:

MyTabs.tsx (w/o Mock Data)

So far, we do not have any mock data to display, but that will be taken care of later. Let us have a look at what is happening in MyTabs.tsx. Setting the initialPage property on Tabs to “1” will ensure that “Chats” will be the selected Tab when the app loads. For each Tab, we set the appropriate styles to make them similar to WhatsApp’s.

Custom components

We will have to render each tab’s content within the corresponding Tab component. Therefore, let us create the following three files inside src/components: Chats.tsx, Status.tsx and Calls.tsx.

Open up Chats.tsx and add to it the following:

Chats.tsx

Using the List, and ListItem components, we will render the contacts and their chat snippets under the “Chats” tab. We can suppose that we will receive the data to display as an Array, chats, through the components props. With that, we pass this.props.chats to dataArray property of List and use keyExtractor to assign a unique key to each element which will be rendered within this List.

renderRow will dictate how each item in the List will look like. And of course, here is where Moment.js can come in handy. We suppose chat.time to be of type Date. So we pass it to Moment() and chain format() to the returned object in order to format the date into a short string that displays the time. We also set a FAB button to the bottom-right of the screen.

Head over to Status.tsx, and write in it the following:

Status.tsx

In this component, we pretty much render the same list, but with some modifications and a couple of ListItems above it. The first ListItem displays the status of the current user, and so we use the URI of the user’s avatar from the component’s props. The second ListItem serves a divider between the first ListItem and the List. I wrote getFormatedDate() function to return a string, from the Date parameter, in the required format, and display that in each ListItem. This should do it for this component!

Finally, open up components/Calls.tsx and copy and paste in it the following:

Calls.tsx

The implementation here is pretty straightforward. The only noticeable difference here is the Button set on the right-hand side of each ListItem. With that, our custom components are ready and each can be used as content for a tab.

Adding Mock Data

Return to components/MyTabs.tsx and let’s modify it to render the custom components under the corresponding tabs and pass some mock data to fill up those components. MyTabs.tsx should now look like this:

MyTabs.tsx with Mock Ddata

I defined three interfaces in order to understand what kind of data objects we are passing to the components as props. Technically, we could have used only a single interface and array for all the components props, since the information to be displayed in the components is, more or less, alike. However, this should give you a better idea how the data objects in a real-world application would be structured. Often you will have data objects of different structures (interfaces) and each, possibly, passed to a different component.

state is assigned to all the data objects we will need in our components. Practically, you would probably retrieve these data from a server by calling a REST API, and later assign them to the component’s state. For simplicity, we will retrieve them from getChats(), getStatusItems(), and getCalls(). Within the tags of each Tab component, we render the component that corresponds to the content of that tab. We also pass the data stored in state as props, for example: <Status statusItems={this.state.statusItems} user={this.state.user} />.

Now, save your project and check out the running emulator.

WhatsApp UI Clone

And that is it!

Up to this point, we should have a decent clone of WhatsApp’s main page. Congrats! You should now have a good idea on how easy it is to build apps using React Native.

Again, here you will find the complete code of this tutorial.

Follow the steps in README to set it up. If you have any questions or comments, drop them below.

Don’t forget to CLAP, if you liked this tutorial.

See you in part 3 for the comparison!

--

--