Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
React: Cross-Platform Application Development with React Native
React: Cross-Platform Application Development with React Native

React: Cross-Platform Application Development with React Native: Build 4 real-world apps with React Native

Arrow left icon
Profile Icon Martinez
Arrow right icon
€17.99 €26.99
eBook Mar 2018 182 pages 1st Edition
eBook
€17.99 €26.99
Paperback
€32.99
Subscription
Free Trial
Renews at €18.99p/m
Arrow left icon
Profile Icon Martinez
Arrow right icon
€17.99 €26.99
eBook Mar 2018 182 pages 1st Edition
eBook
€17.99 €26.99
Paperback
€32.99
Subscription
Free Trial
Renews at €18.99p/m
eBook
€17.99 €26.99
Paperback
€32.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Table of content icon View table of contents Preview book icon Preview Book

React: Cross-Platform Application Development with React Native

Chapter 2. Project 2 – Image Sharing App

At this point, we know how to create a fully-featured app with a custom interface. You even learned how to add a state management library to control shared data in our app so that the code base remains maintainable and scalable.

In this lesson, we will focus on building the app with a different state management library (Redux), using the camera capabilities, writing platform-specific code, and diving deeper into building a custom user interface, which is both appealing and usable. An image sharing app will serve as a good example for these features and also will set up the basis for understanding how big apps should be built on React Native.

We will reuse most of our code for the two platforms where this app will be available: iOS and Android. Although most of our user interface will be custom, we will use native-base to simplify UI elements as icons. For navigation, we will use react-navigation again as it provides the most commonly...

Overview

One of the main requirements when building an image sharing app is an appealing design. We will follow the design patterns for some of the most popular image sharing apps, adapting those patterns for each platform while trying to reuse as much code as possible taking advantage of React Native's cross-platform capabilities.

Let's first take a look at the user interface in iOS:

Overview

The main screen shows a simple header and a list of images, including the user picture, name, and a More icon to share the image. At the bottom, the tabbed navigation displays three icons representing the three main screens: All Images, My Images, and Camera.

Note

All images used for this sample app are free to be used in any form.

When a user presses the More icon for a specific image, the Share menu will be displayed:

Overview

This is a standard iOS component. It doesn't make much sense to use it on a simulator, it can be better tested on an actual device.

Let's take a look at the second screen, My...

Setting up the Folder Structure

Let's initialize a React Native project using React Native's CLI. The project will be named imageShare and will be available for iOS and Android devices:

react-native init --version="0.44.0" imageShare

In order to use some packages in this app, we will be using a specific version of React Native (0.44.0).

We will be using Redux for our app, so we will create a folder structure in which we can accommodate our reducers, actions, components, screens, and api calls:

Moreover, we have added logo.png in the img folder. For the rest, we have a very standard React Native project. The entry point will be index.ios.js for iOS and index.android.js for Android:

/*** index.ios.js and index.android.js ***/ 

import { AppRegistry } from 'react-native';
import App from './src/main';

AppRegistry.registerComponent('imageShare', () => App);

We have the same implementation for both files as we want to use src/main.js as the common...

Overview


One of the main requirements when building an image sharing app is an appealing design. We will follow the design patterns for some of the most popular image sharing apps, adapting those patterns for each platform while trying to reuse as much code as possible taking advantage of React Native's cross-platform capabilities.

Let's first take a look at the user interface in iOS:

The main screen shows a simple header and a list of images, including the user picture, name, and a More icon to share the image. At the bottom, the tabbed navigation displays three icons representing the three main screens: All Images, My Images, and Camera.

Note

All images used for this sample app are free to be used in any form.

When a user presses the More icon for a specific image, the Share menu will be displayed:

This is a standard iOS component. It doesn't make much sense to use it on a simulator, it can be better tested on an actual device.

Let's take a look at the second screen, My Images:

This is a grid...

Setting up the Folder Structure


Let's initialize a React Native project using React Native's CLI. The project will be named imageShare and will be available for iOS and Android devices:

react-native init --version="0.44.0" imageShare

In order to use some packages in this app, we will be using a specific version of React Native (0.44.0).

We will be using Redux for our app, so we will create a folder structure in which we can accommodate our reducers, actions, components, screens, and api calls:

Moreover, we have added logo.png in the img folder. For the rest, we have a very standard React Native project. The entry point will be index.ios.js for iOS and index.android.js for Android:

/*** index.ios.js and index.android.js ***/ 

import { AppRegistry } from 'react-native';
import App from './src/main';

AppRegistry.registerComponent('imageShare', () => App);

We have the same implementation for both files as we want to use src/main.js as the common entry point for both platforms.

Let's jump into...

Redux


Redux is a predictable state container for JavaScript apps based on simple principles:

  • The whole state of your app is stored in an object tree inside a single store

  • The only way to change the state tree is to emit an action, an object describing what happened

  • To specify how the actions transform the state tree, you write pure reducers

Its popularity comes from the degree of consistency, testability, and developer experience that can be derived from its use in any kind of code base (frontend or backend). It's also simple to reason and master due to its strict unidirectional data flow:

User triggers and Actions that are processed by Reducers, which are just pure functions applying changes to the state based on that Action. The resulting state is saved in a single Store, which is used by the View in our app to display the current state of the application.

Redux is a complex topic that falls out of the scope of this book, but it will be extensively used throughout some of the lessons in this...

ImagesList


The main screen in our app is a list of images retrieved from the backend. We will display this images together with their corresponding uploader profile pictures and names. For each image, we will show More, which can be used to share the image with other apps on the user's device, such as messaging apps or social networks. Most of the UI for this screen will be derived from the <Gallery /> component, so we will focus on connecting the screen with Redux store, adding a custom header, and a scroll view to make the gallery scrollable, and adding an activity indicator to warn the user about network activity:

/*** src/components/ImagesList ***/

import React from 'react';
import { View, ScrollView } from 'react-native';

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';
import { Icon } from 'native-base';

import Header from '../components/Header';
import Gallery from '../components/Gallery';
import ActivityIndicator...

Gallery


Gallery holds all the rendering logic for the list of images. It relies on native-base and, more specifically, on two of its components, <List /> and <ListItem />:

/*** src/components/Gallery ***/

import React from 'react';
import { List, ListItem, Text, Icon, Button, Container, Content }
 from 'native-base';
import { Image, Dimensions, View, Share, ActivityIndicator, StyleSheet } from 'react-native';

var {height, width} = Dimensions.get('window');

export default class Gallery extends React.Component {
  _share(image) {
   Share.share({message: image.src, title: 'Image from: ' + 
                image.user.name}) 
  }

  render() {
    return (
      <View>
        <List style={{margin: -15}}>
          {
            this.props.imageList && this.props.imageList.map((image) =>  
            {
              return (
                <ListItem 
                    key={image.id} 
                    style={{borderBottomWidth: 0, 
             ...

Header


We want to reuse a custom header between several screens. That's why it's best to create a separate component for it and import it in those screens:

/*** src/components/Header ***/

import React from 'react';
import { View, Image, StyleSheet } from 'react-native';
import { Icon, Button } from 'native-base';
import { Platform } from 'react-native';

export default class Header extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        {
          Platform.OS === 'android' &&
          <Button transparent onPress={this.props.onMenuButtonPress}>
            <Icon android='md-menu' style={styles.menuIcon}/>
          </Button>
        }
        <Image source={require('../../img/logo.png')} 
          style={styles.logo} />
        {
          Platform.OS === 'android' &&
          <Button onPress={this.props.onCameraButtonPress} transparent>
            <Icon name='camera' style={styles.cameraIcon...

ActivityIndicator


Our custom ActivityIndicator is a very simple component:

/*** src/components/ActivityIndicator ***/

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

export default class CustomActivityIndicator extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <ActivityIndicator style={{marginRight: 10}}/>
        <Text>{this.props.message}</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    justifyContent: 'center',
    padding: 10,
    backgroundColor: '#f0f0f0'
  }
});

It receives a message as a prop and displays it next to a standard spinner. We also added a custom background color (#f0f0f0) to make it more visible over the white backgrounds.

Let's move now to the camera screen to add our images to the list.

Camera


Most of the logic when taking photos can be abstracted when using react-native-camera, so we will focus on using this module in our component and making sure we connect it to our app's state through Redux actions:

/*** src/screens/Camera ***/

import React, { Component } from 'react';
import {
  Dimensions,
  StyleSheet,
  Text,
  TouchableHighlight,
  View
} from 'react-native';
import { Button, Icon } from 'native-base';
import Camera from 'react-native-camera';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';

class CameraScreen extends Component {
  static navigationOptions = {
    tabBarIcon: ({ tintColor }) => (
      <Icon name='camera' style={{fontSize: 40, color: tintColor}}/>
    ),
  };

  render() {
    return (
      <View style={styles.container}>
        <Camera
          ref={(cam) => {
            this.camera = cam;
          }}
          style={styles.preview}
          aspect...

MyImages


This screen shows all the images the logged user has uploaded. We are using fake images for this screen to pre-fill this screen, but more images can be added through the camera screen.

Most of the rendering logic will be moved to a separate component named <ImagesGrid />:

/*** src/screens/MyImages ***/

import React from 'react';
import { 
  Image,
  TouchableOpacity,
  Text,
  View,
  ActivityIndicator,
  Dimensions 
} from 'react-native';

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';
import { Icon } from 'native-base';

import Header from '../components/Header';
import ImagesGrid from '../components/ImagesGrid';

var {height, width} = Dimensions.get('window');

class MyImages extends React.Component {
  static navigationOptions = {
    drawerLabel: 'My Images',
    tabBarIcon: ({ tintColor }) => (
      <Icon name='person' style={{fontSize: 40, color: tintColor}}/>
    )
  };

  componentWillMount...

ImageGrid


A simple scroll view and a list of images. This component is as simple as that, but it's configured in a way that allows the images to flow like a grid in an easy way:

/*** src/components/ImageGrid ***/

import React from 'react';
import { 
  Image,
  TouchableOpacity, 
  ScrollView, 
  Dimensions, 
  View,
  StyleSheet
} from 'react-native';

var {height, width} = Dimensions.get('window');

export default class ImagesGrid extends React.Component {
  render() {
    return (
      <ScrollView>
        <View style={styles.imageContainer}>
          {
            this.props.images && 
            this.props.images.map(img => {
              return (<Image style={styles.image} 
              key={img.id} source={{uri: img.src}}/>);
            })
          }
        </View>
      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
  imageContainer: {
    flexDirection: 'row',
    alignItems: 'flex-start',
    flexWrap: 'wrap'
  },...

Actions


As we see on our screens, there are only two actions needed for this app, fetchImages (for all users or for a specific user) and addImage:

/*** src/actions/index ***/

import api from '../api';

export function fetchImages(userId = null) {
  let actionName, actionNameSuccess, actionNameError;
  if(userId) {
    actionName = 'FETCH_USER_IMAGES';
    actionNameSuccess = 'FETCH_USER_IMAGES_SUCCESS';
    actionNameError = 'FETCH_USER_IMAGES_ERROR';
  } else {
    actionName = 'FETCH_IMAGES';
    actionNameSuccess = 'FETCH_IMAGES_SUCCESS';
    actionNameError = 'ADD_IMAGE_ERROR';
  }

  return dispatch => {
    dispatch({ type: actionName });
    api
      .fetchImages(userId)
      .then(images => {
        dispatch({ 
          type: actionNameSuccess,
          images
        })  
      })
      .catch(error => {
        dispatch({ 
          type: actionNameError,
          error
        });  
      });
  };
}

export function addImage(data = null) {
  return dispatch =&gt...

Reducers


In Redux, reducers are functions in charge of updating the state as new actions happen. They receive the current state and the action (including any payload) and return a new state object. We won't go deep into how reducers work, we just need to understand their basic structure:

/*** src/reducers/index ***/

const initialState = {
  images: null,
  userImages: null,
  error: null,
  user: {
    id: 78261,
    name: 'Sharer1',
    pic: 'https://cdn.pixabay.com/photo/2015/07/20/12/53/
          man-852762_960_720.jpg'
  }
}

export default function (state = initialState, action) {
  switch(action.type){
    case 'FETCH_IMAGES': 
      return Object.assign({}, state, {
        images: [],
        fetchingImages: true,
        error: null
      });
    case 'FETCH_IMAGES_SUCCESS': 
      return Object.assign({}, state, {
        fetchingImages: false,
        images: action.images,
        error: null
      });
    case 'FETCH_IMAGES_ERROR': 
      return Object.assign({}, state, {
...

API


In a real-world app, we would place all the calls to our backend in a separate api folder. For educational purposes, we just mocked the two API calls that are core to our app, addImage and fetchImages:

/*** src/api/index ***/

export default {
  addImage: function(image) {
    return new Promise((resolve, reject) => {
      setTimeout(()=>{
        resolve( '<imgUrl>' );
      }, 3000)
    })
  },
  fetchImages: function(user = null){
    const images = [
      
      {id: 1, src: '<imgUrl>', user: {pic: '<imgUrl>', name: 'Naia'}},
      {id: 2, src: '<imgUrl>', user: {pic: '<imgUrl>', 
       name: 'Mike_1982'}},
      {id: 5, src: '<imgUrl>', user: {pic: '<imgUrl>', 
       name: 'Sharer1'}},
      {id: 3, src: '<imgUrl>', user: {pic: '<imgUrl>', name: 'Naia'}},
      {id: 6, src: '<imgUrl>', user: {pic: '<imgUrl>', 
       name: 'Sharer1'}},
      {id: 4, src: '<imgUrl>', user: {pic: '<imgUrl>', 
 ...
Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Build quirky and fun projects from scratch and become efficient with React Native
  • Learn to build professional Android and iOS applications using your existing JavaScript knowledge
  • Use isomorphic principles to build mobile apps that offer a native user experience
  • Embedded with assessments that will help you revise the concepts you have learned in this course

Description

React Native helps web and mobile developers to build cross-platform apps that perform at the same level as any other natively developed app. The range of apps that can be built using this library is huge. From e-commerce to games, React Native is a good fit for any mobile project due to its flexibility and extendable nature. This project-based book consists of four standalone projects. Each project will help you gain a sound understanding of the framework and build mobile apps with native user experience. Starting with a simple standalone car booking app, you will progressively move on to building advanced apps by adding connectivity with external APIs, using native features, such as the camera or microphone, in the mobile device, integrating with state management libraries such as Redux or MobX, or leveraging React Native’s performance by building a full-featured game. This book is ideal for developers who want to build amazing cross-platform apps with React Native. This book is embedded with useful assessments that will help you revise the concepts you have learned in this book. This book is repurposed for this specific learning experience from the content of Packt's React Native Blueprints by Emilio Rodriguez Martinez.

Who is this book for?

This book is for developers who want to build amazing cross-platform apps with React Native.

What you will learn

  • Structure React Native projects to ease maintenance and extensibility
  • Optimize a project to speed up development
  • Use external modules to speed up the development and maintenance of your projects
  • Explore the different UI and code patterns to be used for iOS and Android
  • Get to know the best practices when building apps in React Native

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Mar 13, 2018
Length: 182 pages
Edition : 1st
Language : English
ISBN-13 : 9781789139600
Vendor :
Facebook
Category :
Languages :

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want

Product Details

Publication date : Mar 13, 2018
Length: 182 pages
Edition : 1st
Language : English
ISBN-13 : 9781789139600
Vendor :
Facebook
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 69.98
React Native Blueprints
€36.99
React: Cross-Platform Application Development with React Native
€32.99
Total 69.98 Stars icon

Table of Contents

5 Chapters
1. Project 1 – Car Booking App Chevron down icon Chevron up icon
2. Project 2 – Image Sharing App Chevron down icon Chevron up icon
3. Project 3 – Messaging App Chevron down icon Chevron up icon
4. Project 4 – Game Chevron down icon Chevron up icon
5. Assessment Answers Chevron down icon Chevron up icon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook? Chevron down icon Chevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website? Chevron down icon Chevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook? Chevron down icon Chevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support? Chevron down icon Chevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks? Chevron down icon Chevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook? Chevron down icon Chevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.