Mastering React Native

4 (3 reviews total)
By Eric Masiello , Jacob Friedmann
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Building a Foundation in React

About this book

React Native has completely revolutionized mobile development by empowering JavaScript developers to build world-class mobile apps that run natively on mobile platforms. This book will show you how to apply JavaScript and other front-end skills to build cross-platform React Native applications for iOS and Android using a single codebase.

This book will provide you with all the React Native building blocks necessary to become an expert. We’ll give you a brief explanation of the numerous native components and APIs that come bundled with React Native including Images, Views, ListViews, WebViews, and much more. You will learn to utilize form inputs in React Native. You’ll get an overview of Facebook’s Flux data architecture and then apply Redux to manage data with a remote API. You will also learn to animate different parts of your application, as well as routing using React Native’s navigation APIs.

By the end of the book, you will be able to build cutting-edge applications using the React Native framework.

Publication date:
January 2017
Publisher
Packt
Pages
496
ISBN
9781785885785

 

Chapter 1. Building a Foundation in React

There is a common trope within the frontend web development community that boils down to new day, new framework. It is a comment on the velocity at which this profession is changing and evolving. The rapid pace can be exhausting, but it is also exciting because of what it represents. The domain of frontend developers seems to be ever expanding-from simple web pages to web applications, mobile applications, and beyond-and with that, the number of smart people contributing ideas and code to the collective knowledge bank is also expanding.     

With all of that said, any sane person must pick and choose which developments to tune into. When React.js emerged on to the open source scene in May 2013 from the inner-sanctum of Facebook, it would have been easy to brush this library off as just another frontend library. That, however, would have been a mistake. It could be said that React was the most significant and influential open source development in frontend technology in recent memory. Its growth beyond the web and its application in the realm of mobile development through React Native is both a testament to its popularity and a boon to its potential utility.

React Native is a library for creating native mobile applications using familiar web technologies that is built on top of React. What this means is that in order to understand React Native, we must first explore React. In this chapter, we'll examine the fundamentals of React. First, we'll talk briefly about the circumstances that led to React being created. We'll also cover these React concepts:

  • JSX, a JavaScript/HTML hybrid that we use to describe React components

  • React components

  • Component composition

  • Component properties, or props

  • Handling events

  • Component state

  • The React component lifecycle

  • Alternate component forms

Note

A note to the reader: this chapter focuses on React for the web, the original purpose of the library. This provides important context for the remainder of the book. If you already know React for the web, then it is probably safe to skip this chapter and proceed to Chapter 2, Saying Hello World in React Native.

 

Library versus framework


When people describe React, they often eschew the description of framework-a description often used for something such as Backbone or Angular-in favor of library. The reason for this more lightweight description is that React is not a complete solution for application development. It is often relegated to only a view-layer solution, and that characterization is mostly correct. React has some mechanisms for maintaining internal state, but it has no opinion about or solutions for data flow and management, server communication, routing, or other common frontend application concerns.

React, therefore, is often coupled with some other library or libraries to create a fully fleshed out application. The most common pairing is with an application architecture that is also the brainchild of the wizards at Facebook called Flux. Flux is not a library in and of itself; it is a set of design patterns that have been implemented by many different libraries, which will be discussed in more depth in Chapter 5, Flux and Redux.

 

Motivation for React


React and the community, libraries, and patterns that surround it are very much a reaction (pun intended) to some of the most frustrating and prevalent issues that plague JavaScript applications as they grow in size and complexity. JavaScript was not designed for creating large applications; it was designed, famously, in just 10 days as a scripting language to add a modicum of interactivity to lifeless web pages.

Chief among these concerns is the unpredictability that comes with shared mutable state. Historically, passing around JavaScript objects that represent the application's state to different views and controllers has been common practice. The ease with which those objects can be mutated by a rogue view, wisdom notwithstanding, can lead to hard-to-diagnose bugs, especially as applications and teams grow.

The foundational building block in a React application is the component, which is a declarative description of some visual feature on the page, such as a form or a menu. The declarative nature of components promotes predictability: given some set of external inputs (properties), the output is well defined and deterministic.

React also aims to combat one of the hurdles to writing efficient applications: the Document Object Model (DOM) is notoriously slow. If changes to the DOM are relatively infrequent, this may not be a problem, but in a complex application the time it takes to alter and redraw the DOM can add up. This is especially true for applications that take a declarative approach as React does, which necessitates re-rendering whenever the application's state changes.

The solution proposed by the React framework is to keep a representation of the DOM in memory, called a virtual DOM, and make all alterations there. Once the alterations have been made in memory, React can apply the minimum number of changes necessary to reconcile the real DOM with the virtual DOM. This also can allow quickly successive changes to be batched for greater efficiency. Taking this approach can lead to great gains in performance that can be noticed by end users.

In addition to solving some of the common problems faced when creating JavaScript applications, React components are modular and emphasize composition over inheritance, which makes code immensely reusable and testable. Additionally, a React component often has rendering logic, markup declaration, and even styles in the same file, which promotes the portability of code and the ability to write shared libraries of components.

Perhaps the most compelling reason to use React and React Native is the astounding amount of community adoption that has taken place in the last two years. People are excited about this technology, and rightly so; it is a novel approach to developing frontend applications that is, by most accounts, accelerating the development time on teams that choose to adopt it. With React Native, the idealistic promise of learn once, write anywhere is becoming more and more viable.

 

Getting started in React


To begin creating an interface in React, the first thing we need to do is break down the interface into conceptual components. We start with a large component, for instance, a news feed. We then say our large component is made up of, or composed of, other smaller components. In the case of our news feed, these smaller components might be individual news items. Each news item, in turn, might be composed of several even smaller components, such as images, a description, and a byline.

This process should continue until the smallest components are bite-sized, reusable visual units that can no longer be easily broken down into smaller pieces. Doing this exercise sets us up well for writing our first code in React. Here is what this process might look like for our hypothetical news reader application.

First, identify and give a name to the largest component we can find, in this case, a NewsFeed:

Now, draw boxes around the next largest set of components, the NewsItem components:

Next, we can zoom in on a single NewsItem and identify the components that it is made of. Here, we can see that there is an Image, a Title, a Description and a Byline:

We've now laid the groundwork to start creating a React application. We have identified six components and their relationships: the NewsFeed, which is composed of NewsItem components, which in turn are composed of Image, Title, Description, and Byline components.

 

Describing components in JSX


In recent years, there have been many developments in JavaScript as a language itself. For instance, the new ECMAScript 2015 (ES2015-sometimes called ES6) specification, which defines the next version of JavaScript, is becoming increasingly solidified. If a developer wishes to write in ES2015-and many do-they need to use a program to convert the newer syntax into one that is compatible with the majority of browsers. Additionally, there are a number of JavaScript-like syntaxes, such as CoffeeScript and TypeScript, that ultimately have to be converted to browser-compatible JavaScript in order to function.

With all of these developments and alternate syntaxes, many developers have become accustomed to transforming code into browser-compatible JavaScript instead of writing it directly. When Facebook created React, they capitalized on this and created a syntax similar to HTML that could be used to describe components. It's called JavaScript XML (JSX), and it is a declarative markup language that is written in tandem with JavaScript to define a component's layout.

Using JSX is not an absolute requirement for writing React, but without it, React becomes verbose and cumbersome. Furthermore, since most developers will be using tools such as Babel already to convert their ES2015 code into JavaScript, writing in JSX does not add much burden because most of those tools come with support for JSX built in.

JSX looks almost exactly like HTML:

<h1> 
  Hello World! 
</h1> 

It differs from HTML5 only slightly. HTML and JSX have a common ancestor language called XML (Extensible Markup Language). HTML has since diverged in some ways from strict XML that JSX has not. For instance, in the case of a tag such as the image tag (that is, <img>) HTML and JSX differ. The <img> tag is called self-closing in that there is no standalone closing tag like we might see with a <div> or a <p>. For a self-closing tag in HTML, a forward slash before the end is optional:

HTML: <img src="my/image.jpg" > 

In JSX (and XML, for that matter), this forward slash is required:

JSX: <img src="my/image.jpg" /> 

There are other differences between JSX and HTML that arise from JSX being written in the context of JavaScript. The first is that class is a keyword in JavaScript, whereas that word is used as an attribute of HTML elements to allow elements to be targeted by CSS for styling. So, when we would use class in HTML, we instead have to use className in JSX:

HTML: <div class="news-item"> 
JSX: <div className="news-item"> 

A consolation prize for this small inconvenience is we get the benefit of being able to interleave JavaScript into places in our markup where we typically wouldn't in normal HTML. For instance, defining inline styles can use a JavaScript object, rather than cramming all properties into a string.

HTML: <div styles="background: green; color: red;"> 
JSX: <div styles={{background: 'green', color: 'red'}}> 

Notice here that there are two sets of curly braces on the style attribute's value. The outer set of curly braces is used to show that the code contained is JavaScript. The inner set is a JavaScript object literal containing the CSS style property names and their respective values.

Not only can attribute values be written in JavaScript, but so too can the content contained between JSX tags. This way, we can use dynamic properties to render text content:

HTML: <span>Hello World</span> 
JSX: <span>{'Hello' + 'World!'}</span> 

As we'll see in coming section, there are more tags available to us than we would see in normal HTML. In fact, our application-defined components themselves can be added into JSX markup:

<NewsItem> 
  Hello React! 
</NewsItem> 

Understanding JSX is paramount to starting to create React components; however, JSX makes up only a part of a complete component.

 

The component


In React, we build applications using composable, modular components. These components represent parts of our visual interface and are rendered as such. In their most simple form, they are simply a description of how to render. We create a component by using ES2015 class syntax:

import React, { Component } from 'react'; 
 
class Title extends Component { 
 
  render() { 
    return ( 
      <h1> 
        Hello World! 
      </h1> 
    ); 
  } 
} 

Since the only requirement is that a render() method is defined, this is now a valid and complete (albeit not especially useful) React component.

In a typical React application project, a component will be self-contained within a file. Files that contain JSX, such as a component file, sometimes have a .jsx extension in web projects; however, this practice is less common in React Native projects. This extension helps tools such as Babel know how to transform them into browser-compatible JavaScript. The entire contents of the file that defines and exports the Title component, Title.jsx, might look like this:

import React, { Component } from 'react'; 
export default class Title extends Component { 
 
  render() { 
    return ( 
      <h1> 
        Hello World! 
      </h1> 
    ); 
  } 
} 

This simple component by itself is not very compelling. So far, everything we've seen in this component could easily be created using only HTML. Rest assured, React provides several ways of making this component more interesting and useful.

 

Component composition


As was mentioned earlier in this chapter, React favors composition over inheritance. What does this mean? In essence, it means to build complex or derivative components, instead of using something akin to object-oriented inheritance, we use composition to build up complexity from simple building blocks.

Our Title component is pretty simple, but we can build up a more complex NewsItem component from the Title component and other simple components:

import React, { Component } from 'react'; 
 
class NewsItem extends Component { 
 
  render() { 
    return ( 
      <div className="news-item"> 
        <Image /> 
        <Title /> 
        <Byline /> 
        <Description /> 
      </div> 
    ); 
  } 
 
} 

The JSX returned by the render method of a component is that component's declarative definition. When that JSX includes other components, such as the <Image />, <Title />, <Byline />, and <Description /> elements we see in the preceding code, it is said to be composed of those components.

Composition has other uses besides making increasingly more complex components from smaller, simpler building blocks. Composition can also be used to make derivative components, a task that in an object-oriented programming world we might use inheritance to achieve. For instance, imagine we want to make a component that is a WarningTitle. This component might share many properties with a Title component, but also add bright red border around it in order to draw a user's attention:

import React, { Component } from 'react'; 
 
class WarningTitle extends Component { 
 
  render() { 
    return ( 
      <div style={{ border: '1px solid red' }}> 
        <Title /> 
      </div> 
    ); 
  } 
 
} 

Using the previous definition, we would then say that WarningTitle is composed of Title because the latter is returned in the render() method of the former.

 

Props and PropTypes


The components that we've seen so far are completely static in that they take no external input and always render exactly the same. This isn't especially interesting because the same outcome can be achieved by writing plain old HTML. However, React provides a mechanism for making components dynamic by using properties, or props.

Accepting props

Props are passed into a component in order to modify their base definition. Let's take another look at our Title component:

import React, { Component } from 'react'; 
 
export default class Title extends Component { 
 
  render() { 
    return ( 
      <h1> 
        Hello World! 
      </h1> 
    ); 
  } 
 
} 

While the title of a single article might be Hello World!, this component needs to be more dynamic if it is to be reused within all of our NewsItem components. For this, we'll use a React input property, or prop, called titleText. React component methods have a this context that gives access to properties that have been passed in:

import React, { Component } from 'react'; 
 
export default class Title extends Component { 
 
  render() { 
    return ( 
      <h1> 
        {this.props.titleText} 
      </h1> 
    ); 
  } 
 
} 

Once again, remember that curly brackets in JSX denotes JavaScript code. Here, we are accessing the component's titleText prop in order to render it within the component's markup:

<h1> 
  {this.props.titleText} 
</h1> 

PropTypes

This by itself is sufficient code to start accepting a titleText property. However, as a best practice, we should include in our component's definition a description of what properties it is equipped to accept. While this may seem like over-engineering and unnecessary in small projects maintained by a single developer, as the project and team grows, explicit definition of properties is key in an untyped language such as JavaScript.

Defining PropTypes in a component is how we formally tell other developers what properties a component accepts and what value types those properties should be. PropTypes are the same across instances of a component and are thus statically attached to the class:

import React, { Component, PropTypes } from 'react'; 
 
export default class Title extends Component { 
 
  render() { 
    return ( 
      <h1> 
        {this.props.titleText} 
      </h1> 
    ); 
  } 
 
} 
 
Title.propTypes = { 
  titleText: PropTypes.string 
}; 

Adding PropTypes to a component does not change anything functionally, but it will cause annoying warning messages to be logged to the JavaScript console when they are disobeyed (only when React is in development mode, mind you).

To use PropTypes, we'll need to add it to the React import:

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

The PropTypes module comes with functions for validating different value types, such as string, number, and func.

Here, what we are communicating is that this component takes one optional property called titleText, and that property should be of type string:

Title.propTypes = { 
  titleText: PropTypes.string 
}; 

We could also make this a required property:

Title.propTypes: { 
  titleText: PropTypes.string.isRequired 
} 

In addition to having string type props, we can also have other simple types, such as booleans and numbers:

Title.propTypes = { 
  titleText: PropTypes.string.isRequired, 
  highlighted: PropTypes.bool, 
  fontSize: PropTypes.number 
}; 

Props can not only be used to define the text content, but can also be used to define attributes of an element, for instance, inline style:

import React, { Component, PropTypes } from 'react'; 
 
export default class Title extends Component { 
 
  render() { 
    return ( 
      <h1 
        style={{ 
          backgroundColor: this.props.highlighted ? 'yellow' : 'white', fontSize: `${this.props.fontSize}px` 
        }} 
      > 
      {this.props.titleText} 
      </h1> 
 
    ); 
  } 
 
} 
 
Title.propTypes = { 
  titleText: PropTypes.string.isRequired, 
  highlighted: PropTypes.bool, fontSize: PropTypes.number 
}; 

One thing to note with the preceding example is that CSS properties that have a dash in them when written in traditional CSS use camel case in React inline style. This is because keys in JavaScript objects cannot contain dashes.

React PropType specifications can also be used to validate more complex properties. For instance, we could have a property that is either a string or a number using the oneOfType function, which is as follows:

fontSize: PropTypes.oneOfType([ 
  PropTypes.string, 
  PropTypes.number 
]) 

Likewise, we can specify a set of specific values that a property is allowed to take by using the oneOf method:

size: PropTypes.oneOf([ 
  'small', 
  'medium', 
  'large' 
]) 

We can of course specify more complex data types, such as arrays and objects, but we can also be more specific and describe the types of values in an array property or the shape that an object property takes:

propTypes: { 
  //Array that can contain anything 
  simpleArray: PropTypes.array, 
 
  //Object that can contain anything 
  simpleObject: PropTypes.object, 
 
  //Array that contains only Number values 
  arrayOfNumbers: PropTypes.arrayOf(PropTypes.number), 
 
  //Object that takes a specific "shape" 
  complexObject: PropTypes.shape({ 
    id: PropTypes.number, 
    name: PropTypes.string 
  }) 
} 

Now our Title component is getting interesting. It has gone from something that can be easily recreated using just HTML to something more like a HTML template-still declaratively defined, but dynamic in that it can take external properties.

Alternatively, PropTypes can be added to a React component as a static property using the static keyword:

import React, { Component, PropTypes } from 'react'; 
 
export default class Title extends Component { 
 
  static propTypes = { 
    titleText: PropTypes.string.isRequired, 
    highlighted: PropTypes.bool, 
    fontSize: PropTypes.number
} 
 
  render() { 
    return ( 
      <h1 
        style={{ 
          backgroundColor: this.props.highlighted ? 'yellow' : 'white', fontSize: `${this.props.fontSize}px` 
        }} 
      > 
        {this.props.titleText} 
      </h1> 
 
    ); 
  } 
 
} 

This syntax is cleaner, but is not officially part of the ECMAScript specification at this point. While most transpiler programs will recognize this syntax, we'll avoid it in this book for that reason.

Passing props

With a component defined that accepts props, the next step is for props to be passed into this component. In the case of our Title component, the NewsItem component can pass properties into the contained Title component. It does this using the attribute syntax of XML:

import React, { Component } from 'react'; 
import Title from './Title'; 
 
export default class NewsItem extends Component { 
 
  render() { 
    return ( 
      <div className="news-item"> 
        <Image /> 
        <Title 
          titleText="Hello World!" 
          highlighted={true} 
          fontSize={18} 
        /> 
        <Byline /> 
        <Description /> 
      </div> 
    ); 
  } 
 
} 

Strings are the only value types that can be passed in as a prop directly:

titleText="Hello World!" 

For other JavaScript data types, such as numbers, Booleans, and arrays, we must surround the values in curly braces so that they are interpreted correctly as JavaScript:

fontSize={18} 

For Boolean props, we can shorten their input to where the property name's presence is interpreted as true and its absence is interpreted as false, much like in HTML:

<div className="news-item"> 
  <Image /> 
  <Title 
    titleText="Hello World!" 
    highlighted 
    fontSize={18} 
  /> 
  <Byline /> 
  <Description /> 
</div> 

Default props

In a previous section, we specified, using PropTypes, that the titleText property of the Title component is required, but the other two properties are optional. This raises an interesting question: what will the value of those properties be if they are not specified? Well, without any intervention from the component developer, those properties will appropriately have the value undefined when no value is passed in. This could be problematic in some situations.

For our fontSize property, a value of undefined could lead to some unpredictable and potentially error-prone code because it is expecting a number. Luckily for us, React has a mechanism for specifying default values for optional properties that have not been passed in explicitly. This mechanism is a method on the component called defaultProps and we can use it in Title, statically, like this:

import React, { Component, PropTypes } from 'react'; 
 
export default class Title extends Component { 
 
  render() { 
    return ( 
      <h1 
        style={{ 
          backgroundColor: this.props.highlighted ? 'yellow' : 'white', 
          fontSize: `${this.props.fontSize}px` 
        }} 
      > 
        {this.props.titleText} 
      </h1> 
 
    ); 
  } 
 
} 
 
Title.propTypes = { 
  titleText: PropTypes.string.isRequired, 
  highlighted: PropTypes.bool, 
  fontSize: PropTypes.number 
}; 
Title.defaultProps = { 
  highlighted: false, 
  fontSize: 18 
}; 

defaultProps must be a JavaScript object where keys are property names and the values are the default values to use in the case that no values were passed in for that particular property. We can now define a Title component that isn't highlighted and has the default font size of 18 pixels by simply writing the following:

<Title 
  titleText="Hello World!" 
/> 

In context, our NewsItem component is now simplified to this:

import React, { Component } from 'react'; 
import Title from './Title'; 
 
export default class NewsItem extends Component { 
 
  render() { 
    return ( 
      <div className="news-item"> 
        <Image /> 
        <Title 
          titleText="Hello World!" 
          highlighted 
        /> 
        <Byline /> 
        <Description /> 
      </div> 
    ); 
  } 
 
} 

Sometimes, a component will receive its props from several levels above. For instance, maybe NewsFeed specifies the title of an individual NewsItem, rather than having NewsItem provide it statically itself, as we have done in the previous examples. Parameterizing this property allows the NewsItem component to be more generic and reusable:

import React, { Component, PropTypes } from 'react'; 
import Title from './Title'; 
 
export default class NewsItem extends Component { 
 
  render() { 
    return ( 
      <div className="news-item"> 
        <Image /> 
        <Title 
          titleText={this.props.titleText} 
          highlighted 
        /> 
        <Byline /> 
        <Description /> 
      </div> 
    ); 
  } 
 
} 
 
NewsItem.propTypes = { 
  titleText: PropTypes.string.isRequired 
}; 

Here, we have shown how the NewsItem component can accept a property, and in turn, pass it down to the Title component.

Props.children

Every component has an optional special property that is called children. Normal properties, as we have seen, are passed in using something similar to the HTML attribute syntax:

<Title 
  titleText="Hello World" 
/> 

You can also pass in text or other component elements by placing them in between an opening and closing tag. We can refactor our Title component to accept children instead of the titleText prop:

<Title> 
  Hello World 
</Title> 

Now, the render() method of our Title component becomes this:

render() { 
  return ( 
    <h1 
      style={{ 
        backgroundColor: this.props.highlighted ? 'yellow' : 'white', fontSize: `${this.props.fontSize}px` 
      }} 
    > 
      {this.props.children} 
    </h1> 
  ); 
} 

Note that we could now also pass in other React elements into the Title as property by also placing them in between the opening and closing tags:

<Title> 
  Hello World! 
  <img src="icon.png" /> 
</Title> 

When validating the children prop, we can use a special PropTypes called node, which means anything that can be rendered by React:

Title.propTypes = { 
  children: PropTypes.node.isRequired, 
  highlighted: PropTypes.bool, 
  fontSize: PropTypes.number 
}; 
 

Event handlers


In JavaScript development, we often think of our application as reacting to user events on the page. For instance, we may listen for a submit button on the page to be clicked, and when it is, validate a form. Functions that respond to these user events are sometimes dubbed event handlers or event listeners.

In a simple JavaScript application, we register these event handlers by querying the DOM for some element and adding an event listener function to run when the event of interest occurs. Here is how we might do this:

document.querySelector('form').addEventListener('click', validateForm); 
 
function validateForm() { 
  alert('The form is valid!'); 
} 

In the early days of JavaScript, we probably would have used HTML event attributes in order to respond to user events on some element. The equivalent code for this inline approach to event handling might look something like this:

<form onsubmit="validateForm()"> 
  ... 
</form> 

In React, the way we do event handling is more like the inline JavaScript of yesteryear. Elements in React can optionally take event handler properties in order to respond to user inputs. A React element is the portion of a component that is returned from the render function. In other words, it is a description of what we want rendered on the screen, generally written in JSX. Our form from the previous example written in JSX would only have a couple of subtle differences:

<form onSubmit={validateForm}> 

To show an example of event handling in context, let's return to our NewsItem example. Let's imagine that we want our application to respond to a user clicking on the news item. We can do this by creating an event listener function in the component and adding it to the outer element in JSX:

import React, { Component, PropTypes } from 'react'; 
import Title from './Title'; 
 
export default class NewsItem extends Component { 
 
  onClick() { 
    alert(`You've clicked on ${this.props.titleText}`); 
  } 
 
  render() { 
    return ( 
      <div 
        className="news-item" 
        onClick={this.onClick.bind(this)} 
      > 
        <Image /> 
        <Title 
          highlighted 
        > 
          {this.props.titleText} 
        </Title> 
        <Byline /> 
        <Description /> 
      </div> 
    ); 
  } 
 
} 
 
NewsItem.propTypes = { 
  titleText: PropTypes.string.isRequired 
}; 

Take note that we are binding the render method's this context to the onClick method when adding it as a click handler:

onClick={this.onClick.bind(this)} 

We need to do this in order to ensure this has the same meaning in the onClick method as it does in other component methods. This way, we can still access props and call other component methods. However, the better way to bind the this context to the event handler method is to do so within the component's constructor:

constructor(props) { 
  super(props); 
  this.onClick = this.onClick.bind(this); 
} 

Then there is no need to re-bind the event handler in the JSX, which can be simplified:

<div 
  className="news-item" 
  onClick={this.onClick} 
> 

This method is preferred not only because it reduces the amount of typing, but also because React internally optimizes to make it more efficient.

Event listeners in React, much as they do without React, receive an optional argument that is an object representing the user event. We can access this event object in order to suppress default behavior, for instance, in a form submission, by using event.preventDefault(). We can also use the event object to, for example, see what document element was targeted by the action or, in the case of a key press event, see which specific key was pressed by the user. To get access to the event, we just need to add it as a parameter to our event listener method:

onClick(event) { 
  console.log('User event', event); 
  alert(`You've clicked on${this.props.titleText}`); 
} 
 

State


Occasionally, a component will need to keep track of some internal state in addition to the external, read-only, properties that are passed into it. State is necessarily internal to the component and, generally, exclusively tied to some visual display option (for instance, is the component visually expanded or collapsed).

Much in the same way that a component instance can access external properties via this.props, a component instance can access its internal state using this.state. Using internal state, we could optionally show parts of NewsItem only when that item is in an expanded state:

render() { 
  let body = null; 
 
  if (this.state.expanded) { 
    body = ( 
      <div> 
        <Byline /> 
        <Description /> 
      </div> 
    ); 
  } 
 
  return ( 
    <div 
      className="news-item" 
      onClick={this.onClick} 
    > 
      <Image /> 
      <Title 
        highlighted 
      > 
        {this.props.titleText} 
      </Title> 
      {body} 
    </div> 
  ); 
} 

We can see now that the body variable will only be defined if the internal state is expanded. Another thing we can see here is that a <div> element has been added around the description and byline. The reason we do this is because JSX elements must have a single root node in order to return them or store them in a variable. Alternatively, we could have stored each element in its own variable:

render() { 
  let byline = null; 
  let description = null; 
 
  if (this.state.expanded) { 
    byline = <Byline />; 
    description = <Description />; 
  } 
 
  return ( 
    <div 
      className="news-item" 
      onClick={this.onClick} 
    > 
      <Image /> 
      <Title 
        highlighted 
      > 
        {this.props.titleText} 
      </Title> 
      {byline} 
      {description} 
    </div> 
  ); 
} 

While this code is completely valid, we can make it even better by splitting out conditional rendering into a separate method:

renderBody() { 
  if (this.state.expanded) { 
    return ( 
      <div> 
        <Byline /> 
        <Description /> 
      </div> 
    ); 
  } 
  return null; 
} 

Then, we can use this helper method within our main render() method in order to make things a bit clearer:

render() { 
  return ( 
      <div 
        className="news-item" 
        onClick={this.onClick} 
      > 
      <Image /> 
      <Title 
        highlighted 
      > 
      {this.props.titleText} 
      </Title> 
        {this.renderBody()} 
      </div> 
    ); 
  } 

We've now seen how to use internal state to render things conditionally, but we have not yet seen how that state is defined or how it is modified. In React, we can specify the initial values of internal state by assigning them in the constructor of the component. The component's initial state, much like its default properties, should be a JavaScript object:

constructor(props) { 
  super(props); 
 
  this.state = { 
    expanded: false 
  }; 
 
  this.onClick = this.onClick.bind(this); 
} 

This method describes the initial state of a component, but it does not provide us with any means to update that state. In order to update the state of a component, we can use a React component's setState method to assign, or reassign, any internal state value.

Typically, updating state happens as a response to some user input or user event. In the last section, we learned how to define methods that respond to these user events, such as clicks, and how to attach these event listeners to the appropriate React element. Let's modify our onClick event handler to change the expanded state of our component instead of simply alerting:

onClick() { 
  this.setState({ 
    expanded: !this.state.expanded 
  }); 
} 

When we use setState in this way, React will notice that the internal state has changed, and this will trigger a new rendering using the new internal state. For this reason, we should never manipulate the state of a component directly:

//Do not do this 
this.state.expanded = false; 

If we change the internal state directly, React's rendering engine will not become aware of it and the component we see on our page will differ from the one in JavaScript. The same goes for props; they are external and should only be changed as a result of new values being passed in through JSX:

//Also don't do this 
this.props.titleText = 'Hello World!'; 

Now that we've demonstrated how to use internal state to display something conditionally, how to initialize state by setting it in the constructor method, and how to modify internal state in response to some user event using setState, let's look at all of this in context in our NewsItem component:

import React, { Component, PropTypes } from 'react'; 
import Title from './Title'; 
 
export default class NewsItem extends Component { 
 
  constructor(props) { 
    super(props); 
 
    this.state = { 
      expanded: false 
    }; 
 
    this.onClick = this.onClick.bind(this); 
  } 
 
  onClick() { 
    this.setState({ 
      expanded: !this.state.expanded 
    }); 
  } 
 
  renderBody() { 
    if (this.state.expanded) { 
      return ( 
        <div> 
          <Byline /> 
          <Description /> 
        </div> 
      ); 
    } 
    return null; 
  } 
 
  render() { 
    return ( 
      <div 
        className="news-item" 
        onClick={this.onClick} 
      > 
        <Image /> 
        <Title 
          highlighted 
        > 
          {this.props.titleText} 
        </Title> 
        {this.renderBody()} 
      </div> 
    ); 
  } 
 
} 
 
NewsItem.propTypes = { 
  titleText: PropTypes.string.isRequired 
}; 

Now we have a component for our news item that starts out collapsed (not expanded) and not showing the description or byline, but when the user clicks on the news item, it expands to show the two previously hidden elements.

 

The component lifecycle


Every React component that is rendered into the DOM goes through a series of steps before and after rendering. As React component developers, we can hook into these steps, called the component lifecycle, in order to perform tasks or check conditions specific to some stage in that lifecycle:

Mounting the component

Before a component is mounted, which means placed into the DOM for the first time, React will look at that component's class to see if it has a method called componentWillMount defined. Should this method exist, React will invoke it. This method is a good place to do things such as set up timers needed by the component or request data the component needs from the server:

componentWillMount() { 
  //Decrement an internal state counter every second 
  setInterval(() => { 
    this.setState({ 
      secondsLeft: this.state.secondsLeft - 1; 
    }); 
  }, 1000); 
} 

The next step in the component's lifecycle is the first render. The render() method we've seen before. React calls this method and then, the first time, converts the JSX element output to HTML elements and places them in the DOM. In other words, it mounts the component.

Once mounting is complete, the next step in the lifecycle, an optional method called componentDidMount, is called. This is often an integration point for non-React libraries. With that said, a word of warning: it is generally not a good idea to use libraries that manipulate the DOM alongside React. Remember that React works by keeping a virtual representation of the DOM in memory in order to calculate change sets and apply them. When other libraries are modifying the DOM, it can quickly become out of sync with what React expects. This could, and more often than not, will, lead to errors when React tries to reconcile changes:

componentDidMount() { 
  //Integrate with an external library here 
} 

From here, the component is stable and its lifecycle dormant until one of two things happens. The first thing that could happen is the component's parent could pass it new props. The second is some event or interval triggers a change in internal state. These two actions, of course, necessitate a re-render. Before a re-render happens, there are a few other lifecycle methods that will be called.

The update cycle

The first method called during a property update cycle is componentWillReceiveProps. Here, we not only know that the component is about to receive a new set of properties, but we also can see what those properties are and how they compare to the old ones:

componentWillReceiveProps(nextProps) { 
  //an object of new props 
  console.log(nextProps); 
 
  //The current (old) props 
  console.log(this.props); 
} 

This lifecycle method is a good place to update state that is somehow derived from props because it is the only update lifecycle method that is not called for both prop and state changes.

This brings us to the next lifecycle method that is called when either props or state are updated: shouldComponentUpdate. This method is unique among lifecycle methods in that it is the only one that expects a return value. As you may be able to guess, the return value expected is a Boolean. If the method returns true, the lifecycle continues as we expect it. However, if shouldComponentUpdate returns false, the lifecycle is short-circuited here and a re-render does not occur. Within this method, we can see not only the new properties, but also the new state that will be rendered:

shouldComponentUpdate(nextProps, nextState) { 
  if (this.props.uid !== nextProps.uid) { 
    return true; 
  } 
  return false; 
} 

If a component does not define this method, it is always assumed to be true. React, though, gives you the ability to override this behavior. This can become important in large applications with many components and many layers of component nesting. Using shouldComponentUpdate, we can fine-tune when a component re-renders in order to enhance the performance of our application. This is important because, while React is good at optimizing renders, rendering is still computationally expensive and excessive rendering can slow down an application to the point where a user can feel stuttering.

If shouldComponentUpdate returns true (or is not defined by the component), the next step in the lifecycle is componentWillUpdate, which is the last step before re-rendering. Here, like in shouldComponentUpdate, we have access to both the new properties and the new state:

componentWillUpdate(nextProps, nextState) { 
  //Prepare for render! 
} 

At this point, React will call render on the component again, getting its new JSX representation. It will compare this new JSX to the old JSX in the virtual DOM and create a change set to apply to the real DOM. Once this process is complete, we arrive at the next step of the lifecycle, which is componentDidUpdate. This method is very similar to componentWillUpdate, except that it receives the previous properties and state as arguments:

componentDidUpdate(prevProps, prevState) { 
  //Here are the old props 
  console.log(prevProps); 
 
  //And here are the current (new) props 
  console.log(this.props); 
} 

Now, we've completed the update lifecycle. At this point, once again the component remains dormant until another change in properties or state occurs. This process continues over and over again until the component is removed, or unmounted, from the DOM.

Unmounting the component

Just before a component is removed from the DOM, the final stage of the component's lifecycle will be completed. Here, React calls the optional componentWillUnmount method, which receives no arguments.

This method is a good place to clean up anything that the component created over the course of its life. For instance, if the component started an interval upon mounting, here would be a good place to stop that interval. In our componentWillMount example, we showed starting a countdown interval that fired every second after the component mounted. If we store that interval's ID in state, we can then stop the interval when the component is being unmounted:

componentWillMount() { 
  //Save the interval in state 
  this.setState({ 
    tickInterval: setInterval(() => { 
      this.setState({ 
        secondsLeft: this.state.secondsLeft - 1; 
      }); 
    }, 1000); 
  }); 
} 
 
componentWillUnmount() { 
  //Stop the countdown before unmounting 
  clearInterval(this.state.tickInterval); 
} 

While we've gone through and demonstrated how each lifecycle method might be used within a component, it is important to point out that we would very rarely need to use every component lifecycle method in a single component. Remember that each one is optional and need not be defined by the component unless some feature of its functionality necessitates it. In fact, our NewsItem component does not need any of these lifecycle methods to do exactly what we want.

 

Alternate component forms


In React, there are three ways to define a component. The way we've seen so far uses ES2015 classes to define a component and its methods. This is currently the most common method for defining React components and, in fact, the one you'll encounter most often in documentation and in this book.

React.createClass

Before ES2015 and its class syntax became popular and brought into React, the way to define a component was by using the React.createClass function. This function takes as an argument a JavaScript object that describes the component and its methods. This conceptually is very similar to the way we have seen so far, but has some syntactic differences. To demonstrate, let's take a look at what our NewsItem component looks like using this method:

React.createClass({ 
 
  propTypes: { 
    titleText: PropTypes.string.isRequired 
  }, 
 
  getInitialState() { 
    return { 
      expanded: false 
    } 
  }, 
 
  onClick() { 
    this.setState({ 
      expanded: !this.state.expanded 
    }); 
  }, 
 
  renderBody() { 
    if (this.state.expanded) 
      return ( 
        <div> 
          <Byline /> 
          <Description /> 
        </div>; 
      ); 
    } 
    return null; 
  }, 
 
  render() { 
    return ( 
      <div 
        className="news-item" 
        onClick={this.onClick} 
      > 
        <Image /> 
        <Title 
          highlighted 
        > 
          {this.props.titleText} 
        </Title> 
        {this.renderBody()} 
      </div> 
    ); 
  } 
 
}); 

Other than the obvious syntactic differences, there are a few subtle differences in how we define and use components with React.createClass that we should draw our attention to. The first is instead of simply assigning the state in the class constructor, we define a getInitialState method in the component, which returns the initial component state as an object:

getInitialState() { 
  return { 
    expanded: false 
  } 
} 

The next thing we might notice is that, previously, event handler functions were bound to the component's this context either in the constructor or within the event attribute assignment. When using the React.createClass syntax, we have no longer need to explicitly bind the context:

<div 
  className="news-item" 
  onClick={this.onClick} 
> 

We may have also noticed that rather than defining the propTypes statically on the class, we instead do it within the component object:

propTypes: { 
  titleText: PropTypes.string.isRequired 
} 

This component does not need default properties, but if it did, we would also define those inside the component object. We do this by defining a method similar to getInitialState called getDefaultProps that also returns an object:

getDefaultProps() { 
  return { 
    someProp: 'some value' 
  } 
}; 

Functional components

For simple components that maintain no internal state, we can define them simply as functions that take props as input and return JSX elements as output. These components are not only succinct, but may in the future be more performant than components defined in other ways. For these reasons, it is recommended that we use functional components wherever possible.

Because of its simplicity and lack of internal state, our Title component from an earlier section is a good candidate for being a functional component. Here is what that component would look like with this alternate syntax:

const Title = (props) => ( 
  <h1 
    style={{ 
      backgroundColor: props.highlighted ? 'yellow' : 'white', 
      fontSize: `${props.fontSize}px` 
    }} 
  > 
    {props.children} 
  </h1> 
); 

Taking advantage of ES2015 arrow function syntax, our large traditionally defined component has been simplified to a single function.

In addition to not having internal state, functional components don't have lifecycle methods. They can, however, have defaultProps and propTypes that can be specified in the same manner as class components:

Title.propTypes = { 
  titleText: PropTypes.string.isRequired 
}; 
 

Summary


The React library has created a new way to develop user interfaces for web applications through creating declarative and composable components in the new, but familiar, JSX syntax. Since its introduction, it has grown immensely in popularity. At Facebook's F8 developer conference in 2016, it was estimated that upwards of 250,000 developers were using React in some way. This enthusiasm led the community to look for new places to use their favorite library, and in early 2015, React Native was born.

In this chapter, we covered the fundamentals of React, from conception to implementation. We learned how to take a user interface and structure it as components, the building blocks of React applications. Starting with simple components, such as a static title, we then built up to more complex components by adding props, event handlers, state, and lifecycle methods. Finally, we looked at some alternate ways of representing React components and discussed when each was appropriate.

In the next chapter, we will take this knowledge of React into the realm of native mobile applications by building a Hello World application in React Native.

About the Authors

  • Eric Masiello

    Eric Masiello is a lead software engineer for Vistaprint Digital. Formerly, Eric worked as a principal frontend engineer for the Advisory Board Company and built mobile apps for the Education Advisory Board. Eric has worked primarily as a frontend/UI developer for over 10 years and freelances as a website designer/developer at http://www.synbydesign.com. He has taught frontend topics at General Assembly in Washington, D.C. and was a technical reviewer for Mastering ReactJS, a video by Packt Publishing.

    You can follow him here:

    Browse publications by this author
  • Jacob Friedmann

    Jacob Friedmann is a developer living in Seattle, WA. He has been working as a developer professionally for 5 years and is currently a principal software engineer at AddThis, an Oracle company. At AddThis, he works on large front and backend applications. He also builds mobile applications using React Native, including Audicy (http://audicy.io), which will soon be launched on the App Store. He has taught several classes, including frontend web development and JavaScript development through General Assembly in Washington D.C.

    You can follow him here:

    Browse publications by this author

Latest Reviews

(3 reviews total)
Preço muito bom e qualidade do material também.
Excellent products purchased
The examples in "Mastering React Native" do not work properly in the current version of React Native. Please make sure that sample code can be run "as is", just to get started.

Recommended For You

Book Title
Unlock this full book with a FREE 10-day trial
Start Free Trial