Build a React Native Twitter UI Replica

Gbenga Oni
Sep 8, 2018 · 9 min read
React native Twitter UI Replica

For this app, we will need access to a simple api we can get random data from so we will go with RandomUser Api.

React native is very powerful and its amazing the amount of magic that can be achieved with it.

Lets setup a fresh react native environment:

react-native init Twitter

Cd into our project folder and run the fresh app on either IOS or Androidemulator. We will use the android emulator in the course of this article.

cd Twitter

Command to run our app on the android emulator (Make sure you have your android emulator already running) :

react-native run-android

For IOS:

react-native run-ios

Great! Now that our environment is set up, lets get our hands dirty. We will install all dependencies needed to build our Twitter app. We will be making use of React Navigation — a routing and navigation helper for React Native apps built to replace the now deprecated NavigatorExperimental and the not so powerful Navigator, a JS-based solution launched with React Native.

We will also be using Axios — a promise based http client for javascript — to make api calls for data fetching, and also React Native Vector Icons.

To install these dependencies, run the following command in your Twitterdirectory:

npm install react-navigation axios react-native-vector-icons

Run npm install again incase you encounter any errors after refresh

We want to create a LoadingScreen component. This is usually where authentication and necessary local app data fetching is done before switching to the main app. We wont be performing any authentication but we will be having a screen that displays the huge twitter bird, the one that comes on when the Twitter app is opened. Let’s create a LoadingScreen component for this:

Create a Loading.js file in your /screens folder. We will use the Entypo twitter logo, which will be placed at the center of the screen. The Loading.js file should look like this:

Now lets go back to our App.js file. We will remove the export default in front of the App class, then export in its stead the AppNavigator, a SwitchNavigator that switches between the loading screen and the app screen, setting the LoadingScreen as the initial route, that is when we open the app, the LoadingScreen is displayed first.

Make sure you import the LoadingScreen and the SwitchNavigator:

import {SwitchNavigator} from ‘react-navigation’
import LoadingScreen from ‘./screens/Loading’

Lets reload the app to see changes made:

Note: if you are using an android emulator and the twitter icon happens to not show, add the following line to your andoid/app/build.gradlefile:

apply from: “../../node_modules/react-native-vector-icons/fonts.gradle”

save, then run react-native run-android again.

😀 Our SwitchNavigator now works perfectly, switching between the LoadingScreen and the App

Creating the App

As everyone who has or is using the Twitter app knows, Twitter uses a slidable drawer navigator. Lets implement this in our App stack.

create a AppStack drawer Navigator with the createDrawerNavigatorfunction provided by react-navigation:

The AppStack component will contain links to the Home and Profile page.

Replace the App component to which the App route in our previous AppNavigator component points to with our newly created AppStackcomponent. This way, when the SwitchNavigator, switches from the LoadingScreen to the App screen, it points to the AppStack component.

{
AuthLoading: LoadingScreen,
App: AppStack,
}

Make sure you import the createStackNavigation function from react-navigation :

import {SwitchNavigator, createDrawerNavigator} from 'react-navigation'

Lets refresh our app to see these changes; do this by hitting the ‘R’ key twice on your keyboard, if your are using an emulator, or otherwise by shaking your physical device.

React Native drawerNavigator

Our drawer navigator now works.

React Native offers a default look for drawer navigators but in this case we need to design this to look as it would in a real Twitter app.

This is where the custom content component for React Navigation drawers come in.

We can achieve this by specifying a custom component with the contentComponentproperty of the createDrawerNavigatorfunction:

custom drawer component

We tell createDrawerNavigator through its contentComponent props to use the DrawerContainer component we will be creating as its default look.

Now lets create the DrawerContainer component:

Create a screens/DrawerContainer.js file:

Import the DrawerContainer:

import DrawerContainer from './screens/DrawerContainer'

Lets refresh the app to see the changes:

custom drawer navigator

We now have a custom drawer navigator.

For y’all Twitter DayMode lovers, sorry NightMode fan here 😜

The custom drawer component receives the navigation props from the Drawer Navigator. This enables the routing to the other screens in the drawer by calling itsnavigate method, for instance:

onPress={() => navigation.navigate('Profile')}

The above code routes the user to the Profile route registered in the Drawer Navigator.

You can specify your own image in the stead of the avatar.png image used in the drawer navigator.

Now that our Drawer Navigator is up and running, lets design the home page, which will contain a TabNavigator of four tabs: Home, Search, Notifications, DM.

The TabNavigator in React Native provides a tab-based style of navigation, one very common on most mobile apps. They can be positioned either at the top or at the bottom of the screen.

Twitter uses a bottom tab navigator, so we will be creating a bottom tab navigator with the createTabNavigator function, which has other derivates like the createMaterialBottomTabNavigator and createMaterialTopTabNavigator, although outside the scope of this article. But you can refer to the official React Navigation documentation for a more comprehensive information.

Lets create a Tab Navigator:

The HomeTabs component is created with the createTabNavigator function which takes objects as arguments, specifying the route name and their corresponding components, and also the navigation options through the object’s navigationOptions property.

We have specified icons that will represent each of these tabs through the navigationOptions property, which is a function that accepts an object argument with atabBarIcon props.

Lets import all the react-native-vector-icons types used :

import Ionicons from 'react-native-vector-icons/Ionicons'import Octicons from 'react-native-vector-icons/Octicons'import EvilIcons from 'react-native-vector-icons/EvilIcons'import FontAwesome from 'react-native-vector-icons/FontAwesome'

For this article, we will only design the Home tab, which is your regular timeline with series of tweets. We will however create a dummy page for the rest of the tabs (Search, Notifications and DM).

Dummy Page:

The Dummy page is a component that displays a blank page with the huge twitter icon at its center, just like we did for the LoadingScreen component.

Don’t forget to import the Entypo icon:

import Entypo from 'react-native-vector-icons/Entypo'

Now that we have our DummyScreen for the rest of the tabs, lets create a simple page for the home tab then check to see what our app looks like:

  • Replace the yet to exist Home component that the Home route of ourHomeTabs component points to with a page that displays ‘hello, this is your timeline’:
Home: {screen: ()=> <View>
<Text>Hello, this is your timeline</Text>
</View>,
},
Search: {
.
.

We are getting there!!

We have successfully set up our tab navigator.

On clicking the home icon, we are taken to the screen that shows “Hello, this is your timeline”.

We will now redesign this page to contain tweets like it would on a timeline.

Designing the Timeline:

The timeline will be a ListViewwhich we will give a padding at the top that equals the navigation bar — which will have an absolute positioning — in height.

We will have 3 animated values:

  • scrollAnimatedValue: representing the current scroll y position of our ListView
  • navOffsetAnimatedValue: this will help us position the navigation bar. With it, we can decide to show or hide the navigation bar at the end of each scroll, depending on the direction of said scroll.
  • clampedScroll: This will help us animate the navigation bar. It is the result of the addition of scrollAnimatedValue and navOffsetAnimatedValue given to the Animated.diffClamp function. It will help show the navigation bar when scrolling up and to hide it when scrolling down.

Read more about Animated.diffClamp here

Now lets attach the animated values to the views and also add some interpolations in order to map them to the translation of the navigation bar view.

Read more about React native Animated here

When the user stops scrolling, and the navigation bar is half collapsed, it will look better to render it either to a fully displayed state or a fully hidden state. We will achieve this by adding functionalities to detect the event at which a scroll ends :onScrollEndDrag ,onMomentumScrollBegin and onMomentumScrollEndfunctions.

A short timer is started at onScrollEndDrag and its cleared in onMomentumScrollBegin .

When the user scrolls normally, the method that handles animating the navigation bar is delayed for some milliseconds before its called. On the other hand, if its a fast/momentous scroll, the timer is cleared and our method will get called in onMomentumScrollEnd.

That said, we need to know whether to hide or show the navigation bar, which requires that we know the values of the Animated values used.

We will achieve this by adding listeners to said values then save it in an instance variable to be accessed in the onMomentumScrollEnd method. Note that the same calculations done in diffClamp will be done manually because the values returned from Animated.diffClamp does not support the addition of listeners.

componentWillUnmount() {this.state.scrollAnim.removeAllListeners();
this.state.offsetAnim.removeAllListeners();
}

The onMomentumScrollEnd method contains the logic to hide or show the navigation bar. We will animate the offset. By adding to its current value, the navigation bar is hidden, while its shown by subtracting from its current value:

We check the clampedScrollValue whether or not it’s passed half of the navigation bar. We will also make sure we don’t hide it while we haven’t scrolled yet, to avoid showing a blank space where the navigation bar is supposed to be.

Now that we have setup the animation for the timeline, we can proceed to implement a ListView of tweets.

Creating a reusable tweet component

Create a screens/Tweet.js file. Tweet.js will be a reusable component used across the app which displays a singular tweet as shown in the image below.

tweet component

We will design our Tweet.js component like the above then import it to the home screen (Home.js)

Tweet.js uses Random Words module module to generate random words of a certain number as tweet content.

Now that we have a reusable tweet component, we will get random user profiles from the randomuser.me api, and we will generate words as tweet with the Random Words module then pass these data to the tweet component through the ListViewwhich will serve as our timeline.

Here is the final code for our Home.js component:

We are making some progress!

Our timeline screen now contains a ListView of series of tweets generated by fetching random user data and random words to form sentences that acts as their respective tweets.

Here is a link to the Git repo:

Conclusion:

We have designed a night mode Twitter React Native Replica that utilizes the Random User Api to get random user data and also the Random Words module to generate random sentences in form of tweets. In the Part II of this article, we will design the user profile page, the create tweet screen and the tweet thread screen.

Comments and suggestions are highly welcome.

Gbenga Oni

Written by

👨🏽‍🎓CS 👨🏽‍💻Software & DevOps Engineer ☁️ AWS Consultant | 2x AWS Certified. Laravel | Express.js | Python | React(Native) | Docker https://gbengaoni.com

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade