Elvis Miranda

Elvis Miranda

1570627252

Cloning Tinder Using React Native Elements and Expo

In this tutorial, we’ll be cloning the most famous dating app, Tinder. We’ll then learn about a UI framework called React Native Elements, which makes styling React Native apps easy.

Since this is just going to be a layout tutorial, we’ll be using Expo, as it makes setting things up much easier than plain old react-native-cli. We’ll also be making use of a lot of dummy data to make our app.

Prerequisites

For this tutorial, you need a basic knowledge of React Native and some familiarity with Expo. You’ll also need the Expo client installed on your mobile device or a compatible simulator installed on your computer. Instructions on how to do this can be found here.

You also need to have a basic knowledge of styles in React Native. Styles in React Native are basically an abstraction similar to that of CSS, with just a few differences. You can get a list of all the properties in the styling cheatsheet.

Throughout the course of this tutorial we’ll be using yarn. If you don’t have yarn already installed, install it from here.

Also make sure you’ve already installed expo-cli on your computer.

If it’s not installed already, then go ahead and install it:

$ yarn global add expo-cli

To make sure we’re on the same page, these are the versions used in this tutorial:

  • Node 11.14.0
  • npm 6.4.1
  • yarn 1.15.2
  • expo 2.16.1

Make sure to update expo-cli if you haven’t updated in a while, since expo releases are quickly out of date.

We’re going to build something that looks like this:

Tinder Demo in Expo

If you just want to clone the repo, the whole code can be found on GitHub.

Getting Started

Let’s set up a new Expo project using expo-cli:

$ expo init expo-tinder

It will then ask you to choose a template. You should choose tabs and hit Enter.

Expo Init - Choose A Template

Then it will ask you to name the project. Type expo-tinder and hit Enter again.

Expo Init - Name the Project

Lastly, it will ask you to press y to install dependencies with yarn or n to install dependencies with npm. Press y.

Expo Init - Install the dependencies

This bootstraps a brand new React Native app using expo-cli.

React Native Elements

React Native Elements is a cross-platform UI Toolkit for React Native with consistent design across Android, iOS and Web.

It’s easy to use and completely built with JavaScript. It’s also the first UI kit ever made for React Native.

It allows us to fully customize styles of any of our components the way we want so every app has its own unique look and feel.

It’s also open source and backed by a community of awesome developers.

You can build beautiful applications easily.

React Native Elements Demo

Cloning Tinder UI

We’ve already created a project named expo-tinder.

To run the project, type this:

$ yarn start

Press i to run the iOS Simulator. This will automatically run the iOS Simulator even if it’s not opened.

Press a to run the Android Emulator. Note that the emulator must be installed and started already before typing a. Otherwise it will throw an error in the terminal.

It should look like this:

Expo Tabs App

Navigation

The initial setup has already installed react-navigation for us. The bottom tab navigation also works by default because we chose tabs in the second step of expo init. You can check it by tapping on Links and Settings.

The screens/ folder is responsible for the content displayed when the tabs are changed.

Now, completely remove the contents of HomeScreen.js and replace them with the following:

import React from 'react'
import { Text, View } from 'react-native'

class HomeScreen extends React.Component {
  render() {
    return (
      <View>
        <Text>Home Screen</Text>
      </View>
    )
  }
}

export default HomeScreen

You should see the updated UI now:

The empty Home screen

Now we’ll adapt the tabs according to the application we’re going to build. For our Tinder clone, we’re going to have four screens: Home, Top Picks, Profile, and Messages.

We can completely delete LinksScreen.js and SettingsScreen.js from the screens/ folder. Notice our app breaks, with a red screen full of errors.

This is because we’ve linked to it in the navigation/ folder. Open MainTabNavigator.js in the navigation/ folder. It currently looks like this:

import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';

import TabBarIcon from '../components/TabBarIcon';
import HomeScreen from '../screens/HomeScreen';
import LinksScreen from '../screens/LinksScreen';
import SettingsScreen from '../screens/SettingsScreen';

const HomeStack = createStackNavigator({
  Home: HomeScreen,
});

HomeStack.navigationOptions = {
  tabBarLabel: 'Home',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon
      focused={focused}
      name={
        Platform.OS === 'ios'
          ? `ios-information-circle${focused ? '' : '-outline'}`
          : 'md-information-circle'
      }
    />
  ),
};

const LinksStack = createStackNavigator({
  Links: LinksScreen,
});

LinksStack.navigationOptions = {
  tabBarLabel: 'Links',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon
      focused={focused}
      name={Platform.OS === 'ios' ? 'ios-link' : 'md-link'}
    />
  ),
};

const SettingsStack = createStackNavigator({
  Settings: SettingsScreen,
});

SettingsStack.navigationOptions = {
  tabBarLabel: 'Settings',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon
      focused={focused}
      name={Platform.OS === 'ios' ? 'ios-options' : 'md-options'}
    />
  ),
};

export default createBottomTabNavigator({
  HomeStack,
  LinksStack,
  SettingsStack,
});

Remove references to LinksStack and SettingsStack completely, because we don’t need these screens in our app. It should look like this:

import React from 'react'
import { Platform } from 'react-native'
import {
  createBottomTabNavigator,
  createStackNavigator,
} from 'react-navigation'
import TabBarIcon from '../components/TabBarIcon'
import HomeScreen from '../screens/HomeScreen'

const HomeStack = createStackNavigator({
  Home: HomeScreen,
})

HomeStack.navigationOptions = {
  tabBarLabel: 'Home',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon
      focused={focused}
      name={
        Platform.OS === 'ios'
          ? `ios-information-circle${focused ? '' : '-outline'}`
          : 'md-information-circle'
      }
    />
  ),
}

export default createBottomTabNavigator({
  HomeStack,
})

Go ahead and create TopPicksScreen.js, ProfileScreen.js and MessagesScreen.js inside the screens/ folder.

Add the following inside TopPicksScreen.js:

import React from 'react'
import { Text, View } from 'react-native'

class TopPicksScreen extends React.Component {
  render() {
    return (
      <View>
        <Text>Top Picks Screen</Text>
      </View>
    )
  }
}

export default TopPicksScreen

Add the following inside ProfileScreen.js:

import React from 'react'
import { Text, View } from 'react-native'

class ProfileScreen extends React.Component {
  render() {
    return (
      <View>
        <Text>Profile Screen</Text>
      </View>
    )
  }
}

export default ProfileScreen

Add the following inside MessagesScreen.js:

import React from 'react'
import { Text, View } from 'react-native'

class MessagesScreen extends React.Component {
  render() {
    return (
      <View>
        <Text>Messages Screen</Text>
      </View>
    )
  }
}

export default MessagesScreen

Let’s go ahead and change components/TabBarIcon.js, since we’ll be needing custom icons on our bottom tab navigation. It currently looks like this:

import React from 'react';
import { Icon } from 'expo';

import Colors from '../constants/Colors';

export default class TabBarIcon extends React.Component {
  render() {
    return (
      <Icon.Ionicons
        name={this.props.name}
        size={26}
        style={{ marginBottom: -3 }}
        color={this.props.focused ? Colors.tabIconSelected : Colors.tabIconDefault}
      />
    );
  }
}

The only thing we’re doing here is adding an Icon prop so we can have different types of Icon instead of just Ionicons. Currently, the different supported types are AntDesign, Entypo, EvilIcons, Feather, FontAwesome, FontAwesome5, FontAwesome5Brands, Foundation, Ionicons, MaterialCommunityIcons, MaterialIcons, SimpleLineIcons, Octicons and Zocial.

You can choose a variety of different icons from the @expo/vector-icons directory. It adds a compatibility layer around @oblador/react-native-vector-icons to work with the Expo asset system.

TabBarIcon.js should now look like this:

import React from 'react'
import Colors from '../constants/Colors'

export default class TabBarIcon extends React.Component {
  render() {
    const { Icon, name, focused } = this.props
    return (
      <Icon
        name={name}
        size={26}
        style={{ marginBottom: -3 }}
        color={focused ? Colors.tabIconSelected : Colors.tabIconDefault}
      />
    )
  }
}

Now we can pass the Icon prop to the above TabBarIcon component to load different icons.

We need to change the implementation of HomeStack in the MainTabNavigator.js folder to incorporate with the new TabBarIcon component’s Icon prop.

Change the HomeStack variable implementation to this:

import { Icon } from 'expo'

const HomeStack = createStackNavigator({
  Home: HomeScreen,
})

HomeStack.navigationOptions = {
  tabBarLabel: 'Home',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon
      Icon={Icon.MaterialCommunityIcons}
      focused={focused}
      name="fire"
    />
  ),
}

The only change here is the addition of Icon={Icon.MaterialCommunityIcons}, since we changed the implementation of TabBarIcon to accept the icon source so we can use different types of icons from different providers.

Now these icons need to be loaded first. Otherwise, we’ll see a flash of empty screen before the icons show up. For that, we need to change App.js by adding the following:

Font.loadAsync({
  // This is the font that we're using for our tab bar
  ...Icon.MaterialIcons.font,
  ...Icon.MaterialCommunityIcons.font,
  ...Icon.FontAwesome.font,
  ...Icon.Feather.font,
}),

These font types are used at some points in our application. That’s why we’ve included only four fonts. For example, MaterialCommunityIcons is used in the HomeStack variable in the MainTabNavigator.js file, as shown above.

We’ll also be hiding our StatusBar in App.js with this:

<StatusBar hidden />

We’ll also replace the assets used in App.js:

Asset.loadAsync([
  require('./assets/images/splash.png'),
  require('./assets/images/icon.png'),
]),

The App.js file should now look like this:

import { AppLoading, Asset, Font, Icon } from 'expo'
import React from 'react'
import { StatusBar, StyleSheet, View } from 'react-native'
import AppNavigator from './navigation/AppNavigator'

export default class App extends React.Component {
  state = {
    isLoadingComplete: false,
  }

  render() {
    if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
      return (
        <AppLoading
          startAsync={this._loadResourcesAsync}
          onError={this._handleLoadingError}
          onFinish={this._handleFinishLoading}
        />
      )
    } else {
      return (
        <View style={styles.container}>
          <StatusBar hidden />
          <AppNavigator />
        </View>
      )
    }
  }

  _loadResourcesAsync = async () => {
    return Promise.all([
      Asset.loadAsync([
        require('./assets/images/splash.png'),
        require('./assets/images/icon.png'),
      ]),
      Font.loadAsync({
        // This is the font we're using for our tab bar
        ...Icon.MaterialIcons.font,
        ...Icon.MaterialCommunityIcons.font,
        ...Icon.FontAwesome.font,
        ...Icon.Feather.font,
      }),
    ])
  }

  _handleLoadingError = error => {
    // In this case, you might want to report the error to your error
    // reporting service, such as Sentry
    console.warn(error)
  }

  _handleFinishLoading = () => {
    this.setState({ isLoadingComplete: true })
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
})

We also need to link all of the above screens—TopPicksScreen.js, ProfileScreen.js and MessagesScreen.js—inside screens/ in MainTabNavigator.js inside the navigation/ folder, as shown in the following flowchart:

Flowchart Demo

Also add the following in MainTabNavigator.js:

import MessagesScreen from '../screens/MessagesScreen'
import ProfileScreen from '../screens/ProfileScreen'
import TopPicksScreen from '../screens/TopPicksScreen'

const TopPicksStack = createStackNavigator({
  TopPicks: TopPicksScreen,
})

TopPicksStack.navigationOptions = {
  tabBarLabel: 'TopPicks',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon Icon={Icon.FontAwesome} focused={focused} name="diamond" />
  ),
}

const MessagesStack = createStackNavigator({
  Messages: MessagesScreen,
})

MessagesStack.navigationOptions = {
  tabBarLabel: 'Messages',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon Icon={Icon.FontAwesome} focused={focused} name="commenting-o" />
  ),
}

const ProfileStack = createStackNavigator({
  Profile: ProfileScreen,
})

ProfileStack.navigationOptions = {
  tabBarLabel: 'Profile',
  tabBarIcon: ({ focused }) => (
    <TabBarIcon Icon={Icon.Feather} focused={focused} name="user" />
  ),
}

The above code creates three stack navigators—TopPicksStack, MessagesStack and ProfileStack. The static property navigationOptions lets us add our own label and icon to the bottom tab.

Also, change createBottomTabNavigator to make sure TopPicksStack, MessagesStack and ProfileStack show up in the bottom tab navigation:

export default createBottomTabNavigator({
  HomeStack,
  TopPicksStack,
  MessagesStack,
  ProfileStack,
})

Now you should be able to see different icons in the bottom tab navigation with different screens as follows:

Different icons in the bottom tab navigation

We now need to get rid of the header that’s showing on each screen, taking up some top space. To get rid of it, we need to add headerMode: 'none' in the createStackNavigator config.

We need to add it on HomeStack, TopPicksStack, MessagesStack and ProfileStack.

HomeStack should look like this:

const HomeStack = createStackNavigator(
  {
    Home: HomeScreen,
  },
  {
    headerMode: 'none',
  },
)

Do the same for the rest of them. Now if you check, the text goes up to the top left, right above the clock.

Different icons in the bottom tab navigation

There’s an easy fix for this. We need to use SafeAreaView. SafeAreaView renders content within the safe area boundaries of a device. Let’s go into the screens/ directory and change HomeScreen.js to use SafeAreaView, so that it looks like this:

import React from 'react'
import { SafeAreaView, Text } from 'react-native'

class HomeScreen extends React.Component {
  render() {
    return (
      <SafeAreaView>
        <Text>Home Screen</Text>
      </SafeAreaView>
    )
  }
}

export default HomeScreen

It now renders the content inside the boundaries of the device.

SafeAreaView added to the app

Go ahead and change the rest of them to do the same.

It’s repetitive to wrap SafeAreaView inside every component instead of setting it up on a root component like App.js. But be aware that this won’t work if you try doing it on App.js.

Remember, SafeAreaView should always be set up on screen components or any content in them, and not wrap entire navigators. You can read more about it on this blog post.

Screens

Now that our navigation is taken care of, we can start working on the layout.

We’re going to be using a UI toolkit called React Native Elements, so go ahead and install it:

$ yarn add react-native-elements

Before starting anything, make sure to copy the assets/ directory from the GitHub repo entirely for dummy images.

Now we’ll start working on the Home screen.

Home Screen

Before starting to work on HomeScreen.js, let’s delete unnecessary files. Go to the components/ folder and delete StyledText.js and the __tests__ folder.

Now let’s start working on our Home screen.

Firstly, create Card.js in the components/ folder. We’re going to display a profile card with the person’s name, their age and how far away they live.

We’re going to use a Tile component from react-native-elements to display our User Card.

The Tile component from react-native-elements looks like this:

Tile component from react-native-elements

import React from 'react'
import { Platform, StyleSheet } from 'react-native'
import { Tile } from 'react-native-elements'
import Layout from '../constants/Layout'

const BOTTOM_BAR_HEIGHT = !Platform.isPad ? 29 : 49 // found from https://stackoverflow.com/a/50318831/6141587

export const Card = ({ pic, title, caption }) => (
  <Tile
    imageSrc={pic}
    imageContainerStyle={styles.imageContainer}
    activeOpacity={0.9}
    title={title}
    titleStyle={styles.title}
    caption={caption}
    captionStyle={styles.caption}
    containerStyle={styles.container}
    featured
  />
)

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
  },
  imageContainer: {
    width: Layout.window.width - 30,
    height: Layout.window.height - BOTTOM_BAR_HEIGHT * 6,
    borderRadius: 20,
    overflow: 'hidden', // this does magic
  },
  title: {
    position: 'absolute',
    left: 10,
    bottom: 30,
  },
  caption: {
    position: 'absolute',
    left: 10,
    bottom: 10,
  },
})

The Card component takes pic, title and caption, which in turn are passed on to the Tile component.

The Tile component has some additional properties. activeOpacity is a number passed to control opacity on pressing the Tile, which is optional, but the default value is 0.2, which makes it look transparent on press, so we pass a value close to 1 to keep it opaque. The featured prop changes the look of Tile. It keeps the text in title and a caption prop on the image rather than below when featured is not specified or is set to false.

The rest are styles applied to get the user card right. The container style centers the user card. imageContainer has a width and a height. The width is set to the total width of the device—30dp (device pixels)—and the height is set to the total height of the device—BOTTOM_BAR_HEIGHT * 6.

We get the BOTTOM_BAR_HEIGHT from stackoverflow.com.

We get the device width from the constants/Layout.js file, which basically contains the following:

import { Dimensions } from 'react-native'

const width = Dimensions.get('window').width
const height = Dimensions.get('window').height

export default {
  window: {
    width,
    height,
  },
  isSmallDevice: width < 375,
}

Then we add a border radius to the image. But the border radius won’t be applied. We also need overflow: hidden to make it work.

Then we position our title and caption to use absolute positioning and make them appear on the bottom-left corner, just above the image.

Next, create a utils/shuffleArray.js file and paste the following into it:

// found at https://stackoverflow.com/a/46545530/6141587
const shuffleArray = array =>
  array
    .map(a => ({ sort: Math.random(), value: a }))
    .sort((a, b) => a.sort - b.sort)
    .map(a => a.value)

export default shuffleArray

This makes sure our array is randomized every time.

Now create a constants/Pics.js file and paste in the following:

import shuffleArray from '../utils/shuffleArray'

export const HomeScreenPics = shuffleArray([
  {
    pic: require('../assets/images/women/women1.jpg'),
    title: 'Amelia, 27',
    caption: '16 miles away',
  },
  {
    pic: require('../assets/images/women/women2.jpg'),
    title: 'Joanna, 19',
    caption: '2 miles away',
  },
  {
    pic: require('../assets/images/women/women3.jpg'),
    title: 'Charlie, 32',
    caption: '24 miles away',
  },
  {
    pic: require('../assets/images/women/women4.jpg'),
    title: 'Mary, 23',
    caption: '45 miles away',
  },
  {
    pic: require('../assets/images/women/women5.jpg'),
    title: 'Lucy, 27',
    caption: '32 miles away',
  },
  {
    pic: require('../assets/images/women/women6.jpg'),
    title: 'Rachel, 29',
    caption: '30 miles away',
  },
  {
    pic: require('../assets/images/women/women7.jpg'),
    title: 'Ava, 31',
    caption: '14 miles away',
  },
  {
    pic: require('../assets/images/women/women8.jpg'),
    title: 'Monica, 35',
    caption: '19 miles away',
  },
  {
    pic: require('../assets/images/women/women9.jpg'),
    title: 'Lisa, 25',
    caption: '7 miles away',
  },
  {
    pic: require('../assets/images/women/women10.jpg'),
    title: 'Julia, 22',
    caption: '9 miles away',
  },
  {
    pic: require('../assets/images/men/men1.jpg'),
    title: 'Aaron, 24',
    caption: '3 miles away',
  },
  {
    pic: require('../assets/images/men/men2.jpg'),
    title: 'Novak, 27',
    caption: '12 miles away',
  },
  {
    pic: require('../assets/images/men/men3.jpg'),
    title: 'Justin, 32',
    caption: '20 miles away',
  },
  {
    pic: require('../assets/images/men/men4.jpg'),
    title: 'Tony, 21',
    caption: '4 miles away',
  },
  {
    pic: require('../assets/images/men/men5.jpg'),
    title: 'Leo, 30',
    caption: '22 miles away',
  },
  {
    pic: require('../assets/images/men/men6.jpg'),
    title: 'Ronald, 39',
    caption: '35 miles away',
  },
  {
    pic: require('../assets/images/men/men7.jpg'),
    title: 'Johnny, 41',
    caption: '44 miles away',
  },
  {
    pic: require('../assets/images/men/men8.jpg'),
    title: 'Chandler, 35',
    caption: '29 miles away',
  },
  {
    pic: require('../assets/images/men/men9.jpg'),
    title: 'Joey, 29',
    caption: '17 miles away',
  },
  {
    pic: require('../assets/images/men/men10.jpg'),
    title: 'Alfie, 37',
    caption: '27 miles away',
  },
])

This contains all the images required for our app. Notice every time we call shuffleArray to randomize our array.

Let’s install react-native-deck-swiper to make sure our cards get swiped like Tinder. The latest version (v1.6.7 at the time of writing) uses react-native-view-overflow, which doesn’t support Expo. Hence, we’re going to install v1.5.25:

$ yarn add react-native-deck-swiper@1.5.25

Now go into the HomeScreen.js file and paste the following:

import React from 'react'
import { SafeAreaView, StyleSheet } from 'react-native'
import Swiper from 'react-native-deck-swiper'
import { Card } from '../components/Card'
import { HomeScreenPics } from '../constants/Pics'

class HomeScreen extends React.Component {
  render() {
    return (
      <SafeAreaView style={styles.container}>
        <Swiper
          cards={HomeScreenPics}
          renderCard={Card}
          infinite // keep looping cards infinitely
          backgroundColor="white"
          cardHorizontalMargin={0}
          stackSize={2} // number of cards shown in background
        />
      </SafeAreaView>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'transparent',
  },
})

export default HomeScreen

Now our cards are swipable, and our home screen looks like this:

Home Screen Demo

Try swiping now, and it should work as follows:

If you want to learn how to make these kinds of Tinder Swipe animations, you should check out Varun Nath’s Tinder Swipe Series on YouTube.

Now that our Home screen is finished, let’s build the Top Picks screen.

Top Picks Screen

Now let’s design the Top Picks screen.

Firstly, go into constants/Pics.js and add the following bit at the end:

export const TopPicksScreenPics = shuffleArray([
  {
    pic: require('../assets/images/women/women11.jpg'),
    title: 'Annie, 40',
    caption: '26h left',
  },
  {
    pic: require('../assets/images/women/women12.jpg'),
    title: 'Lena, 31',
    caption: '20h left',
  },
  {
    pic: require('../assets/images/women/women13.jpg'),
    title: 'Kendra, 19',
    caption: '15h left',
  },
  {
    pic: require('../assets/images/women/women14.jpg'),
    title: 'Mia, 23',
    caption: '45h left',
  },
  {
    pic: require('../assets/images/women/women15.jpg'),
    title: 'Jenny, 27',
    caption: '12h left',
  },
  {
    pic: require('../assets/images/men/men11.jpg'),
    title: 'Dwayne, 34',
    caption: '13h left',
  },
  {
    pic: require('../assets/images/men/men12.jpg'),
    title: 'Novak, 27',
    caption: '22h left',
  },
  {
    pic: require('../assets/images/men/men13.jpg'),
    title: 'Zikomo, 32',
    caption: '20h left',
  },
  {
    pic: require('../assets/images/men/men14.jpg'),
    title: 'Sam, 19',
    caption: '42h left',
  },
  {
    pic: require('../assets/images/men/men15.jpg'),
    title: 'Richard, 31',
    caption: '21h left',
  },
])

These are the images we’ll need in the Top Picks screen.

Now add the following code in TopPicksScreen.js:

import React from 'react'
import { ScrollView, StyleSheet, View } from 'react-native'
import { Text, Tile } from 'react-native-elements'
import { SafeAreaView } from 'react-navigation'
import { TopPicksScreenPics } from '../constants/Pics'

class TopPicksScreen extends React.Component {
  render() {
    return (
      <SafeAreaView>
        <ScrollView>
          <Text h2 h2Style={styles.h2Style}>
            Top Picks
          </Text>
          <Text h4 h4Style={styles.h4Style}>
            Featured profiles of the day, picked just for you
          </Text>
          <View style={styles.grid}>
            {TopPicksScreenPics.map(({ pic, title, caption }, i) => (
              <Tile
                imageSrc={pic}
                activeOpacity={0.9}
                title={title}
                titleStyle={styles.title}
                caption={caption}
                captionStyle={styles.caption}
                featured
                key={title}
              />
            ))}
          </View>
        </ScrollView>
      </SafeAreaView>
    )
  }
}

const styles = StyleSheet.create({
  h2Style: {
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#000000',
  },
  h4Style: {
    textAlign: 'center',
    color: '#757575',
  },
  grid: {
    marginTop: 20,
    marginBottom: 20,
  },
  title: {
    position: 'absolute',
    left: 10,
    bottom: 50,
    backgroundColor: 'black',
    marginBottom: -2,
    padding: 10,
  },
  caption: {
    position: 'absolute',
    left: 10,
    bottom: 0,
    backgroundColor: 'black',
    marginTop: 10,
    padding: 10,
  },
})

export default TopPicksScreen

Firstly, we use the basic Text component found in react-native-elements with a heading and a subheading.

Then we loop through all the images we just added in constants/Pics.js and display them using the Tile component.

The title and caption are placed in center by default, but we’ve moved them to the bottom left with position:'absolute'.

That concludes our Top Picks screen, which was very simple.

It looks like this:

Top Picks screen demo

Messages Screen

Now let’s get started with the Messages screen. Firstly, we need some dummy data to display on the listicles.

Create Messages.js in the constants/ folder and paste in the following:

import shuffleArray from '../utils/shuffleArray'

export const Messages = shuffleArray([
  {
    pic: require('../assets/images/women/women1.jpg'),
    title: 'Amelia, 27',
    message: "Let's get to your favorite restaurant.",
  },
  {
    pic: require('../assets/images/women/women2.jpg'),
    title: 'Joanna, 19',
    message: "What's the best way to win you over?",
  },
  {
    pic: require('../assets/images/men/men2.jpg'),
    title: 'Novak, 27',
    message: 'Will catch up with you later.',
  },
  {
    pic: require('../assets/images/men/men3.jpg'),
    title: 'Justin, 32',
    message: 'Probably not going to work out :(',
  },
  {
    pic: require('../assets/images/women/women3.jpg'),
    title: 'Charlie, 32',
    message: 'How about we go for a coffee on Sunday?',
  },

  {
    pic: require('../assets/images/women/women5.jpg'),
    title: 'Lucy, 27',
    message: 'Sleeping for now.',
  },
  {
    pic: require('../assets/images/men/men1.jpg'),
    title: 'Aaron, 24',
    message: 'See you soon.',
  },
  {
    pic: require('../assets/images/men/men4.jpg'),
    title: 'Tony, 21',
    message: 'Seriously, come on time.',
  },
  {
    pic: require('../assets/images/men/men5.jpg'),
    title: 'Leo, 30',
    message: "What'd you like?",
  },
  {
    pic: require('../assets/images/women/women4.jpg'),
    title: 'Mary, 23',
    message: "Hey, what's up?",
  },
  {
    pic: require('../assets/images/women/women14.jpg'),
    title: 'Michelle, 45',
    message: 'Howdy!!!',
  },
  {
    pic: require('../assets/images/women/women12.jpg'),
    title: 'Arya, 18',
    message: 'Not today!',
  },
])

Next, create MessagesScreen.js in the components/ folder and paste in the following:

import React from 'react'
import { SafeAreaView, ScrollView, StyleSheet } from 'react-native'
import { ListItem } from 'react-native-elements'
import { Messages } from '../constants/Messages'

class MessagesScreen extends React.Component {
  render() {
    return (
      <SafeAreaView>
        <ScrollView>
          {Messages.map((user, i) => (
            <ListItem
              key={i}
              leftAvatar={{ source: user.pic, size: 'large' }}
              title={user.title}
              titleStyle={styles.title}
              subtitle={user.message}
              subtitleStyle={styles.subtitle}
              chevron
            />
          ))}
        </ScrollView>
      </SafeAreaView>
    )
  }
}

const styles = StyleSheet.create({
  title: {
    fontSize: 24,
    color: '#3F3F3F',
  },
  subtitle: {
    color: '#A5A5A5',
  },
})

export default MessagesScreen

We take the dummy data Messages and map over it and put it in a ListItem exported from react-native-elements. The ListItem component displays a list of items one after the other, just like we see on any messages app—with a large avatar, the name of the user, and the message. react-native-elements takes away all the hassle of writing our own listicle for messages so that we can just use five lines of code to make a nice list.

It currently looks like this:

Messages screen demo

Profile Screen

Let’s make the final Profile screen.

First, create a utils/randomNo.js file and paste in the following:

export const randomNo = (min, max) =>
  Math.floor(Math.random() * (max - min) + min)

The function randomNo returns a random number between min and max.

Now open up components/ProfileScreen.js and paste in the following:

import React from 'react'
import { Image, SafeAreaView, StyleSheet, View } from 'react-native'
import { Divider, Icon, Text } from 'react-native-elements'
import Layout from '../constants/Layout'
import { HomeScreenPics } from '../constants/Pics'
import { randomNo } from '../utils/randomNo'

const { pic, title } = HomeScreenPics[randomNo(1, HomeScreenPics.length)]

const Social = ({ name }) => (
  <Icon
    name={name}
    type="font-awesome"
    containerStyle={styles.iconContainer}
    size={32}
  />
)

class ProfileScreen extends React.Component {
  render() {
    return (
      <SafeAreaView style={styles.container}>
        <View style={styles.imageContainer}>
          <Image source={pic} style={styles.image} />
        </View>
        <Text h4 style={styles.name}>
          {title}
        </Text>
        <Text style={styles.desc}>Fashion Designer at Amelia & Co.</Text>
        <Divider style={styles.divider} />
        <Text style={styles.desc}>
          I love to travel. I have a cat named pickles. If he likes you, I
          probably will too.
        </Text>
        <Divider style={styles.divider} />
        <Text style={styles.desc}>Find me on Social here</Text>
        <View style={styles.socialLinks}>
          <Social name="snapchat" />
          <Social name="instagram" />
          <Social name="facebook-square" />
        </View>
      </SafeAreaView>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
  },
  imageContainer: {
    margin: 20,
  },
  image: {
    width: Layout.window.width - 60, // device width - some margin
    height: Layout.window.height / 2 - 60, // device height / 2 - some margin
    borderRadius: 20,
  },
  name: {
    color: '#5E5E5E',
    alignSelf: 'flex-start',
    marginLeft: 30,
  },
  desc: {
    color: '#5E5E5E',
    alignSelf: 'flex-start',
    marginTop: 5,
    marginHorizontal: 30,
    fontSize: 14,
  },
  divider: {
    backgroundColor: '#C0C0C0',
    width: Layout.window.width - 60,
    margin: 20,
  },
  socialLinks: {
    flex: 1,
    alignItems: 'flex-start',
    flexDirection: 'row',
    width: Layout.window.width,
    marginLeft: 40,
  },
  iconContainer: {
    paddingHorizontal: 8,
    paddingVertical: 15,
  },
})

export default ProfileScreen

Let’s decipher the code a bit.

Firstly, we get a random pic and title from the HomeScreenPics array, which is not the first image but can be any of the rest of the images from that array.

Then we’ve created a Social component, looking like this:

const Social = ({ name }) => (
  <Icon
    name={name}
    type="font-awesome"
    containerStyle={styles.iconContainer}
    size={32}
  />
)

This takes in a name as a prop. We use this in our render method. The render method contains the usual SafeAreaView, Text, View, and our custom Social component—with a little bit of styling which we’ve already covered above.

The only unique component here is a Divider component. Dividers are visual separators of content. We use them to make a distinction between different sections of content.

Lastly, we add some styling. That’s it.

It currently looks like this:

Profile screen demo

I’ve also made a repo, in case you want to clone it. You can find it here on GitHub.

Conclusion

We’ve successfully cloned a Tinder UI with a little bit of custom styling and with a lot of help from React Native Elements.

React Native Elements takes all the hassle away while building a beautiful UI by using its pre-made component library.

We could also create everything completely from scratch without using any UI library, but it would require us to write a lot of code—mostly styling. By using a UI library, we can write less code and deliver our application faster.

You can now mimic any UI by taking the smallest part of the UI and building it. Use UI frameworks to write less code and ship faster.

Recommended Reading

React Native Tutorial: Facebook login using React Native FBSDK

Top 20 Best React Templates for Web Apps in 2020

React Native vs Flutter — Which is preferred for you?

How do Navigation for your Mobile app using React Native

#react-native #reactjs

What is GEEK

Buddha Community

Cloning Tinder Using React Native Elements and Expo
Autumn  Blick

Autumn Blick

1598839687

How native is React Native? | React Native vs Native App Development

If you are undertaking a mobile app development for your start-up or enterprise, you are likely wondering whether to use React Native. As a popular development framework, React Native helps you to develop near-native mobile apps. However, you are probably also wondering how close you can get to a native app by using React Native. How native is React Native?

In the article, we discuss the similarities between native mobile development and development using React Native. We also touch upon where they differ and how to bridge the gaps. Read on.

A brief introduction to React Native

Let’s briefly set the context first. We will briefly touch upon what React Native is and how it differs from earlier hybrid frameworks.

React Native is a popular JavaScript framework that Facebook has created. You can use this open-source framework to code natively rendering Android and iOS mobile apps. You can use it to develop web apps too.

Facebook has developed React Native based on React, its JavaScript library. The first release of React Native came in March 2015. At the time of writing this article, the latest stable release of React Native is 0.62.0, and it was released in March 2020.

Although relatively new, React Native has acquired a high degree of popularity. The “Stack Overflow Developer Survey 2019” report identifies it as the 8th most loved framework. Facebook, Walmart, and Bloomberg are some of the top companies that use React Native.

The popularity of React Native comes from its advantages. Some of its advantages are as follows:

  • Performance: It delivers optimal performance.
  • Cross-platform development: You can develop both Android and iOS apps with it. The reuse of code expedites development and reduces costs.
  • UI design: React Native enables you to design simple and responsive UI for your mobile app.
  • 3rd party plugins: This framework supports 3rd party plugins.
  • Developer community: A vibrant community of developers support React Native.

Why React Native is fundamentally different from earlier hybrid frameworks

Are you wondering whether React Native is just another of those hybrid frameworks like Ionic or Cordova? It’s not! React Native is fundamentally different from these earlier hybrid frameworks.

React Native is very close to native. Consider the following aspects as described on the React Native website:

  • Access to many native platforms features: The primitives of React Native render to native platform UI. This means that your React Native app will use many native platform APIs as native apps would do.
  • Near-native user experience: React Native provides several native components, and these are platform agnostic.
  • The ease of accessing native APIs: React Native uses a declarative UI paradigm. This enables React Native to interact easily with native platform APIs since React Native wraps existing native code.

Due to these factors, React Native offers many more advantages compared to those earlier hybrid frameworks. We now review them.

#android app #frontend #ios app #mobile app development #benefits of react native #is react native good for mobile app development #native vs #pros and cons of react native #react mobile development #react native development #react native experience #react native framework #react native ios vs android #react native pros and cons #react native vs android #react native vs native #react native vs native performance #react vs native #why react native #why use react native

Hire Dedicated React Native Developer

Have you ever thought of having your own app that runs smoothly over multiple platforms?

React Native is an open-source cross-platform mobile application framework which is a great option to create mobile apps for both Android and iOS. Hire Dedicated React Native Developer from top React Native development company, HourlyDeveloper.io to design a spectacular React Native application for your business.

Consult with experts:- https://bit.ly/2A8L4vz

#hire dedicated react native developer #react native development company #react native development services #react native development #react native developer #react native

Juned Ghanchi

1621573085

React Native App Developers India, React Native App Development Company

Expand your user base by using react-native apps developed by our expert team for various platforms like Android, Android TV, iOS, macOS, tvOS, the Web, Windows, and UWP.

We help businesses to scale up the process and achieve greater performance by providing the best react native app development services. Our skilled and experienced team’s apps have delivered all the expected results for our clients across the world.

To achieve growth for your business, hire react native app developers in India. You can count on us for all the technical services and support.

#react native app development company india #react native app developers india #hire react native developers india #react native app development company #react native app developers #hire react native developers

Hire Dedicated React Native Developers - WebClues Infotech

Being one of the emerging frameworks for app development the need to develop react native apps has increased over the years.

Looking for a react native developer?

Worry not! WebClues infotech offers services to Hire React Native Developers for your app development needs. We at WebClues Infotech offer a wide range of Web & Mobile App Development services based o your business or Startup requirement for Android and iOS apps.

WebClues Infotech also has a flexible method of cost calculation for hiring react native developers such as Hourly, Weekly, or Project Basis.

Want to get your app idea into reality with a react native framework?

Get in touch with us.

Hire React Native Developer Now: https://www.webcluesinfotech.com/hire-react-native-app-developer/

For inquiry: https://www.webcluesinfotech.com/contact-us/

Email: sales@webcluesinfotech.com

#hire react native developers #hire dedicated react native developers #hire react native developer #hiring a react native developer #hire freelance react native developers #hire react native developers in 1 hour

Factors affecting the cost of hiring a React Native developer in USA - TopDevelopers.co

Want to develop app using React Native? Here are the tips that will help to reduce the cost of react native app development for you.
Cost is a major factor in helping entrepreneurs take decisions about investing in developing an app and the decision to hire react native app developers in USA can prove to be fruitful in the long run. Using react native for app development ensures a wide range of benefits to your business. Understanding your business and working on the aspects to strengthen business processes through a cost-efficient mobile app will be the key to success.

#best react native development companies from the us #top react native app development companies in usa #cost of hiring a react native developer in usa #top-notch react native developer in usa #best react native developers usa #react native