Appendix

JavaScript Versions

JavaScript is the language of the web. It runs on many different browsers, like Google Chrome, Firefox, Safari, Microsoft Edge, and Internet Explorer. React Native takes this one step further and allows us to write JavaScript to communicate with native iOS and Android components.

Its widespread adoption as the internet's client-side scripting language led to the formation of a standards body which manages its specification. The specification is called ECMAScript or ES.

The 5th edition of the specification is called ES5. You can think of ES5 as a version of the JavaScript programming language. The 6th edition, ES2015, was finalized in 2015 and is a significant update. It contains a whole host of new features for JavaScript. JavaScript written in ES2015 is tangibly different than JavaScript written in ES5.

ES2016, a much smaller update that builds on ES2015, was ratified in June 2016.

ES2015 is sometimes referred to as ES6. ES2016, in turn, is often referred to as ES7.

ES2015

Arrow functions

There are three ways to write arrow function bodies. For the examples below, let's say we have an array of city objects:


const cities = [
  { name: 'Cairo', pop: 7764700 },
  { name: 'Lagos', pop: 8029200 },
];

If we write an arrow function that spans multiple lines, we must use braces to delimit the function body like this:


const formattedPopulations = cities.map((city) => {
  const popMM = (city.pop / 1000000).toFixed(2);
  return popMM + ' million';
});
console.log(formattedPopulations);
// -> [ "7.76 million", "8.03 million" ]

Note that we must also explicitly specify a return for the function.

However, if we write a function body that is only a single line (or single expression) we can use parentheses to delimit it:


const formattedPopulations2 = cities.map((city) => (
  (city.pop / 1000000).toFixed(2) + ' million'
));

Notably, we don't use return as it's implied.

Furthermore, if your function body is terse you can write it like so:


const pops = cities.map(city => city.pop);
console.log(pops);
// [ 7764700, 8029200 ]

The terseness of arrow functions is one of two reasons that we use them. Compare the one-liner above to this:


const popsNoArrow = cities.map(function(city) { return city.pop });

Of greater benefit, though, is how arrow functions bind the this object.

The traditional JavaScript function declaration syntax (function () {}) will bind this in anonymous functions to the global object. To illustrate the confusion this causes, consider the following example:


function printSong() {
  console.log("Oops - The Global Object");
}

const jukebox = {
  songs: [
    {
      title: "Wanna Be Startin' Somethin'",
      artist: "Michael Jackson",
    },
    {
      title: "Superstar",
      artist: "Madonna",
    },
  ],
  printSong: function (song) {
    console.log(song.title + " - " + song.artist);
  },
  printSongs: function () {
    // `this` bound to the object (OK)
    this.songs.forEach(function(song) {
      // `this` bound to global object (bad)
      this.printSong(song);
    });
  },
}

jukebox.printSongs();
// > "Oops - The Global Object"
// > "Oops - The Global Object"

The method printSongs() iterates over this.songs with forEach(). In this context, this is bound to the object (jukebox) as expected. However, the anonymous function passed to forEach() binds its internal this to the global object. As such, this.printSong(song) calls the function declared at the top of the example, not the method on jukebox.

JavaScript developers have traditionally used workarounds for this behavior, but arrow functions solve the problem by capturing the this value of the enclosing context. Using an arrow function for printSongs() has the expected result:


function printSong() {
  console.log("Oops - The Global Object");
}

const jukebox = {
  songs: [
    {
      title: "Wanna Be Startin' Somethin'",
      artist: "Michael Jackson",
    },
    {
      title: "Superstar",
      artist: "Madonna",
    },
  ],
  printSong: function (song) {
    console.log(song.title + " - " + song.artist);
  },
  printSongs: function () {
    this.songs.forEach((song) => {
      // `this` bound to same `this` as `printSongs()` (`jukebox`)
      this.printSong(song);
    });
  },
}

jukebox.printSongs();
// > "Wanna Be Startin' Somethin' - Michael Jackson"
// > "Superstar - Madonna"

For this reason, throughout the book we use arrow functions for all anonymous functions.

Classes

JavaScript is a prototype-based language where classes, which is common in many object-oriented languages, were not used. However, ES2015 introduced a class declaration syntax. For example:


class Ball {
  constructor(color) {
    this.color = color;
  }

  details() {
    return 'This ball is ' + this.color + '!';
  }
}

class SoccerBall extends Ball {
  kick() {
    return 'This ' + this.color + 'soccer ball is kicked!';
  }
}

This isn't a brand new JavaScript model, but only a simpler way to define object oriented structures instead of using prototypal-based inheritance. For context, let's take a look at how this would probably look like without using a class definition:


function Ball(color) {
  this.color = color;
}

Ball.prototype.details = function details() {
  return 'This ball is ' + this.color + '!';
};

function SoccerBall(color) {
  Ball.call(this, color);
}

SoccerBall.prototype = Object.create(Ball.prototype);
SoccerBall.prototype.constructor = Ball;

SoccerBall.prototype.kick = function () {
  return 'This ' + this.color + 'soccer ball is kicked!';
}

We won't be going into more detail explaining object oriented paradigms and structures in JavaScript, but it's important to realize that creating objects with properties can be simpler with classes. The important thing to note here is that we use this exact same model to create our React Native components.

If you'd like to learn more about ES6 classes, refer to the docs on MDN.

Shorthand property names

In ES5, all objects were required to have explicit key and value declarations:


const getState = () => {};
const dispatch = () => {};

const explicit = {
  getState: getState,
  dispatch: dispatch,
};

In ES2015, you can use this terser syntax whenever the property name and variable name are the same:


const getState = () => {};
const dispatch = () => {};

const implicit = {
  getState,
  dispatch,
};

Lots of open source libraries use this syntax, so it's good to be familiar with it. But whether you use it in your own code is a matter of stylistic preference.

Destructuring Assignments

For arrays

In ES5, extracting and assigning multiple elements from an array looked like this:


var fruits = [ 'apples', 'bananas', 'oranges' ];
var fruit1 = fruits[0];
var fruit2 = fruits[1];

In ES6, we can use the destructuring syntax to accomplish the same task like this:


const [ veg1, veg2 ] = [ 'asparagus', 'broccoli', 'onion' ];
console.log(veg1); // -> 'asparagus'
console.log(veg2); // -> 'broccoli'

The variables in the array on the left are "matched" and assigned to the corresponding elements in the array on the right. Note that 'onion' is ignored and has no variable bound to it.

For objects

We can do something similar for extracting object properties into variables:


const smoothie = {
  fats: [ 'avocado', 'peanut butter', 'greek yogurt' ],
  liquids: [ 'almond milk' ],
  greens: [ 'spinach' ],
  fruits: [ 'blueberry', 'banana' ],
};

const { liquids, fruits } = smoothie;

console.log(liquids); // -> [ 'almond milk' ]
console.log(fruits); // -> [ 'blueberry', 'banana' ]

Parameter context matching

We can use these same principles to bind arguments inside a function to properties of an object supplied as an argument:


const containsSpinach = ({ greens }) => {
  if (greens.find(g => g === 'spinach')) {
    return true;
  } else {
    return false;
  }
};

containsSpinach(smoothie); // -> true

We can also do this with functional React components.

ReactElement

React Native allows us to build applications with a fake representation of the native views rendered in our mobile device. A ReactElement is a representation of a rendered element.

Consider this JavaScript syntax:


React.createElement(Text, { style: { color: 'red' }},
  'Hello, friend! I am a basic React Native component.'
)

Which can be represented in JSX as:


<Text style={ { color: 'red' } }>
  Hello, friend! I am a basic React Native component.
</Text>

The code readability is slightly improved in the latter example. This is exacerbated in a nested tree structure:


React.createElement(View, {},
  React.createElement(Text, { style: { color: 'red' }},
    'Hello, friend! I am a basic React Native component.'
  )
)

In JSX:


<View>
  <Text style={ { color: 'red' } }>
    Hello, friend! I am a basic React Native component.
  </Text>
</View>

Overall, JSX presents a light abstraction over the JavaScript version, yet the legibility benefits are huge. Readability boosts our app's longevity and makes it easier to onboard new developers.

Handling Events in React Native

Using bind statements within a render() method and property initializers aren't the only ways to handle events. We can also take care of binding our event handlers in a class constructor:


export default class SearchInput extends React.Component {
  constructor() {
    super();

    this.handleChangeText = this.handleChangeText.bind(this);
  }

  handleChangeText(newLocation) {
    // We need to do something with newLocation
  }

  render() {
    const { placeholder } = this.props;

    return (
      <TextInput
        placeholder={placeholder}
        placeholderTextColor="white"
        style={styles.textInput}
        clearButtonMode="always"
        onChangeText={this.handleChangeText}
      />
    );
  }
}

Instead of using a constructor to bind our method, we can also also leverage ES6 arrow syntax to achieve the same effect:


export default class SearchInput extends React.Component {
  handleChangeText(newLocation) {
    // We need to do something with newLocation
  }

  render() {
    const { placeholder } = this.props;

    return (
      <TextInput
        placeholder={placeholder}
        placeholderTextColor="white"
        style={styles.textInput}
        clearButtonMode="always"
        onChangeText={text => this.handleChangeText(text)}
      />
    );
  }
}

Notice how this simplifies our syntax where we don't need to continously set up bind for each of our event handlers. We're specifically using ES6 arrow syntax to pass in the callback:


onChangeText={text => this.handleChangeText(text)}

In most cases this is just fine, but it's important to realize that this callback will instantiate every time TextInput here is rendered. This will also be the case if we use bind statements within our component JSX like we did previously. In most applications, this is unlikely to pose any noticeable performance issues due to additional re-rendering. However, binding our member methods within the constructor actually prevents this from happening.

This is where using property initializers can come in handy:


export default class SearchInput extends React.Component {
  handleChangeText = newLocation => {
    // We need to do something with newLocation
  }

  render() {
    const { placeholder } = this.props;

    return (
      <TextInput
        placeholder={placeholder}
        placeholderTextColor="white"
        style={styles.textInput}
        clearButtonMode="always"
        onChangeText={this.handleChangeText}
      />
    );
  }
}

By using this pattern, we can remove some boilerplate within our constructor method as well as handle events in a cleaner fashion without causing additional re-renders.

Higher-Order Components

A Higher-Order Component (or HOC, for short) sounds complex, but the idea is simple: we want a way to add common functionality (e.g data fetching or drag-and-drop) to many different components. To do this, we write a function that takes an existing component and wraps it in an enhanced component. Instead of changing the code of original component, a higher-order component allows us to change the functionality by controlling how and when we show the original component.

In code, a HOC is conceptually straightforward as well. To create a HOC, we'll create a function that accepts a component to wrap:

const Enhance = OriginalComponent => {
  return props => <OriginalComponent {...props} />;
};

It looks like there is a lot going on in the Enhance function, but it's pretty simple. The function accepts an OriginalComponent argument and returns a stateless component function.

JSX spread syntax

We cover spread syntax, {...props}, in the "React Fundamentals" chapter, but we haven't mentioned we can also use it for component props. Instead of having to know all of the key-value pairs in the props, the spread syntax takes each of the props and sets them as key-value pairs automatically.

For instance, if we have a props object that has two keys:

const props = {msg: "Hello", recipient: "World"}

In spread-syntax, JSX will make the resulting examples equivalent:

<Component {...props} />
<Component msg={"Hello"} recipient={"World"} />