Book Image

React Native By Example

By : Richard Kho
Book Image

React Native By Example

By: Richard Kho

Overview of this book

React Native's ability to build performant mobile applications with JavaScript has resulted in its popularity amongst developers. Developers now have the luxury to create incredible mobile experiences that look and feel native to their platforms with the comfort of a well-known language and the popular React.js library. This book will show you how to build your own native mobile applications for the iOS and Android platforms while leveraging the finesse and simplicity of JavaScript and React. Throughout the book you will build three projects, each of increasing complexity. You will also link up with the third-party Facebook SDK, convert an app to support the Redux architecture, and learn the process involved in making your apps available for sale on the iOS App Store and Google Play. At the end of this book, you will have learned and implemented a wide breadth of core APIs and components found in the React Native framework that are necessary in creating great mobile experiences.
Table of Contents (17 chapters)
Title Page
Credits
Foreword
About the Author
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface

Custom RenderRow component


The final thing on our list to have a usable minimum viable product is to allow each task to be marked as complete. This is where we'll create the TasksListCell component and render that in our renderRow function of ListView instead of just the text.

Our goals for this component should be as follows:

  • Accept text from the parent component as a prop, rendering it in TasksListCell
  • Update listOfTasks to take in an array of objects rather than an array of strings, allowing each object to track the name of the task and whether or not it's completed
  • Provide some sort of visual indicator when a task is tapped, marking it as complete both visually and within the task's data object, so this persists through application reloads

Custom RenderRow example

Let's look at how I created this component:

// Tasks/app/components/TasksList/index.js 

... 
import TasksListCell from '../TasksListCell'; 
... 
export default class TasksList extends Component { 
  ... 
  async _addTask () { 
    const singleTask = { 
      completed: false, 
      text: this.state.text 
    } 

Firstly, tasks are now represented as objects within the array. This allows us to add properties to each task, such as its completed state, and leaves room for future additions.

    const listOfTasks = [...this.state.listOfTasks, singleTask]; 
    await AsyncStorage.setItem('listOfTasks', 
    JSON.stringify(listOfTasks)); 
    this._updateList(); 
  } 
  ... 
  _renderRowData (rowData, rowID) { 
    return ( 
      <TasksListCell 
        completed={ rowData.completed } 
        id={ rowID } 
        onPress={ (rowID) => this._completeTask(rowID) } 
        text={ rowData.text } 
      /> 
    ) 
  } 
  ... 
} 

The _renderRowData method is also updated to render a new TasksListCell component. Four props are shared to TasksListCell: the task's completed state, its row identifier (provided by renderRow), a callback to alter the task's completed state, and the details of that task itself.

Here's how that TasksListCell component was written:

// Tasks/app/components/TasksListCell/index.js 

import React, { Component, PropTypes } from 'react'; 

import { 
  Text, 
  TouchableHighlight, 
  View 
} from 'react-native'; 

export default class TasksListCell extends Component { 
  static propTypes = { 
    completed: PropTypes.bool.isRequired, 
    id: PropTypes.string.isRequired, 
    onLongPress: PropTypes.func.isRequired, 
    onPress: PropTypes.func.isRequired, 
    text: PropTypes.string.isRequired 
  } 

Use PropTypes to explicitly declare the data this component expects to be given. Read on for an explanation on prop validation in React.

  constructor (props) { 
    super (props); 
  } 

  render () { 
    const isCompleted = this.props.completed ? 'line-through' : 'none'; 
    const textStyle = { 
      fontSize: 20, 
      textDecorationLine: isCompleted 
    }; 

Use a ternary operator to calculate styling for a task if it is completed.

    return ( 
      <View> 
        <TouchableHighlight 
          onPress={ () => this.props.onPress(this.props.id) } 
          underlayColor={ '#D5DBDE' } > 
          <Text style={ textStyle }>{ this.props.text }</Text> 
        </TouchableHighlight> 
      </View> 
    ) 
  } 
} 

The preceding component provides a TouchableHighlight for each task on the list, giving us visual opacity feedback when an item is tapped on. It also fires the _completeTask method of TasksListCell, which subsequently calls the onPress prop that was passed to it and makes a visual change to the style of the cell, marking it completed with a line through the horizontal center of the task.