Introduction to React

What is React

React is a JavaScript library that aims to simplify development of visual interfaces.

Developed at Facebook and released to the world in 2013, it drives some of the most widely used code in the world, powering Facebook and Instagram among many, many other software companies.

Its primary goal is to make it easy to reason about an interface and its state in any point in time, by dividing the UI into a collection of components.

React is used to build single-page web applications, among with many other libraries and frameworks that were available before React came into life.

React has taken the frontend web development world by storm. Why?

Less complex than the other alternatives

At the time when React was announced, Ember.js and Angular 1.x were the predominant choices as a framework. Both these imposed too many conventions on the code that porting an existing app was not convienient at all. React made a choice to be very easy to integrate into an existing project, because that’s how they had to do it at Facebook in order to introduce it to the existing codebase. Also, those 2 frameworks bringed too much to the table, while React only chose to implement the View layer instead of the full MVC stack.

Perfect timing

At the time, Angular 2.x was announced by Google, along with the backwards incompatibility and major changes it was going to bring. Moving from Angular 1 to 2 was like moving to a different framework, so this, along with execution speed improvements that React promised, made it something developers were eager to try.

Backed by Facebook

Being backed by Facebook obviously is going to benefit a project if it turns to be successful, but it’s not a guarantee, as you can see from many failed open source projects by both Facebook and Google as an example.

Is React really that simple?

Even though I said that React is simpler than alternative frameworks, diving into React is still complicated, but mostly because of the corollary technologies that can be integrated with React, like Redux, Relay or GraphQL.

React in itself has a very small API.

There isn’t too much into React than these concepts:

  • Components
  • JSX
  • State
  • Props

We’ll see each one of them in the next articles.


JSX

Many developers, including who is writing this article, at first sight thought that JSX was horrible, and quickly dismissed React.

Even though they said JSX was not required, using React without JSX was painful.

It took me a couple years of occasionally looking at it to start digesting JSX, and now I largely prefer it over the alternative, which is: using templates.

The major benefit of using JSX is that you’re only interacting with JavaScript object, not template strings.

JSX is not embedded HTML

Many tutorials for React beginners like to postpone the introduction of JSX later, because they assume the reader would be better off without it, but since I am now a JSX fan, I’ll immediately jump into it.

Here is how you define a h1 tag containing a string:

const element = <h1>Hello, world!</h1>

It looks like a strange mix of JavaScript and HTML, but in reality it’s all JavaScript.

What looks like HTML, is actually a sugar syntax for defining components and their positioning inside the markup.

Inside a JSX expression, attributes can be inserted very easily:

const myId = 'test'
const element = <h1 id={myId}>Hello, world!</h1>

You just need to pay attention when an attribute has a dash (-) which is converted to camelCase syntax instead, and these 2 special cases:

  • class becomes className
  • for becomes htmlFor

because they are reserved words in JavaScript.

Here’s a JSX snippet that wraps two components into a div tag:

<div>
  <BlogPostsList />
  <Sidebar />
</div>

A tag always needs to be closed, because this is more XML than HTML (if you remember the XHTML days, this will be familiar, but since then the HTML5 loose syntax won). In this case a self-closing tag is used.

JSX while introduced with React is no longer a React-only technology.


React Components

What is a React Component

A component is one isolated piece of interface. For example in a typical blog homepage you might find the Sidebar component, and the Blog Posts List component. They are in turn composed by components themselves, so you could have a list of Blog post components, each for every blog post, and each with its own peculiar properties.

A react component

React makes it very simple: everything is a component.

Even plain HTML tags are component on their own, and they are added by default.

The next 2 lines are equivalent, they do the same thing. One with JSX, one without, by injecting <h1>Hello World!</h1> into an element with id app.

import React from 'react'
import ReactDOM from 'react-dom'

ReactDOM.render(
  <h1>Hello World!</h1>,
  document.getElementById('app')
)

ReactDOM.render(
  React.DOM.h1(null, "Hello World!"),
  document.getElementById('app')
)

See, React.DOM exposed us an h1 component. Which other HTML tags are available? All of them! You can inspect what React.DOM offers by typing it in the Browser Console:

Browser console inspecting React.DOM

(the list is longer)

The built-in components are nice, but you’ll quickly outgrow them. What React excels in is letting us compose a UI by composing custom components.

Custom components

There are 2 ways to define a component in React.

A stateless component does not manage internal state, and is just a function:

const BlogPostExcerpt = () => {
  return (
    <div>
      <h1>Title</h1>
      <p>Description</p>
    </div>
  )
}

A stateful component is a class, which manages state in its own properties:

import React, { Component } from 'react'

class BlogPostExcerpt extends Component {
  render() {
    return (
      <div>
        <h1>Title</h1>
        <p>Description</p>
      </div>
    )
  }
}

As they stand, they are equivalent because there is no state management yet (coming in the next couple articles).

There is a third syntax which uses the ES5 / ES2015 syntax, without the classes:

import React from 'react'

React.createClass({
  render() {
    return (
      <div>
        <h1>Title</h1>
        <p>Description</p>
      </div>
    )
  }
})

You’ll rarely see this in modern, > ES6 codebases.

Props is how Components get their properties. Starting from the top component, every child component gets its props from the parent. In a stateless component, props is all it gets passed, and they are available by adding props as the function argument:

const BlogPostExcerpt = (props) => {
  return (
    <div>
      <h1>{props.title}</h1>
      <p>{props.description}</p>
    </div>
  )
}

In a stateful component, props are passed by default. There is no need to add anything special, and they are accessible as this.props in a Component instance.

import React, { Component } from 'react'

class BlogPostExcerpt extends Component {
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <p>{this.props.description}</p>
      </div>
    )
  }
}

PropTypes

Since JavaScript is a dynamically typed language, we don’t really have a way to enforce the type of a variable at compile time, and if we pass invalid types, they will fail at runtime or give weird results if the types are compatible but not what we expect.

Flow and TypeScript help a lot, but React has a way to directly help with props types, and even before running the code, our tools (editors, linters) can detect when we are passing the wrong values:

import PropTypes from 'prop-types';
import React from 'react'

class BlogPostExcerpt extends Component {
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <p>{this.props.description}</p>
      </div>
    )
  }
}

BlogPostExcerpt.propTypes = {
  title: PropTypes.string,
  description: PropTypes.string
};

export default BlogPostExcerpt

Which types can we use

These are the fundamental types we can accept:

  • PropTypes.array
  • PropTypes.bool
  • PropTypes.func
  • PropTypes.number
  • PropTypes.object
  • PropTypes.string
  • PropTypes.symbol

We can accept one of two types:

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

We can accept one of many values:

PropTypes.oneOf(['Test1', 'Test2']),

We can accept an instance of a class:

PropTypes.instanceOf(Something)

We can accept any React node:

PropTypes.node

or even any type at all:

PropTypes.any

Arrays have a special syntax that we can use to accept an array of a particular type:

PropTypes.arrayOf(PropTypes.string)

Objects, we can compose an object properties by using

PropTypes.shape({
  color: PropTypes.string,
  fontSize: PropTypes.number
})

Requiring properties

Appending isRequired to any PropTypes option will cause React to return an error if that property is missing:

PropTypes.arrayOf(PropTypes.string).isRequired,
PropTypes.string.isRequired,

Default values for props

If any value is not required we need to specify a default value for it if it’s missing when the Component is initialized.

BlogPostExcerpt.propTypes = {
  title: PropTypes.string,
  description: PropTypes.string
}

BlogPostExcerpt.defaultProps = {
  title: '',
  description: ''
}

Some tooling like ESLint have the ability to enforce defining the defaultProps for a Component with some propTypes not explicitly required.

How props are passed

When initializing a component, pass the props in a way similar to HTML attributes:

const desc = 'A description'
//...
<BlogPostExcerpt title="A blog post" description={desc} />

We passed the title as a plain string (something we can only do with strings!), and description as a variable.

Children

A special prop is children. That contains the value of anything that is passed in the body of the component, for example:

<BlogPostExcerpt
  title="A blog post"
  description={desc}>
  Something
</BlogPostExcerpt>

In this case, inside BlogPostExcerpt we could access “Something” by looking up this.props.children.

While Props allow a Component to receive properties from its parent, be “instructed” to print some data for example, state allows a component to take life on itself, and be independent of the surrounding environment.

Remember: only class-based Components can have a state, so if you need to manage state in a stateless (function-based) Component, you first need to “upgrade” it to a Class component:

const BlogPostExcerpt = () => {
  return (
    <div>
      <h1>Title</h1>
      <p>Description</p>
    </div>
  )
}

becomes:

import React, { Component } from 'react'

class BlogPostExcerpt extends Component {
  render() {
    return (
      <div>
        <h1>Title</h1>
        <p>Description</p>
      </div>
    )
  }
}

Setting the default state

In the Component constructor, initialize this.state. For example the BlogPostExcerpt component might have a clicked state:

class BlogPostExcerpt extends Component {
  constructor(props) {
    super(props)
    this.state = { clicked: false }
  }

  render() {
    return (
      <div>
        <h1>Title</h1>
        <p>Description</p>
      </div>
    )
  }
}

Accessing the state

The clicked state can be accessed by referencing this.state.clicked:

class BlogPostExcerpt extends Component {
  constructor(props) {
    super(props)
    this.state = { clicked: false }
  }

  render() {
    return (
      <div>
        <h1>Title</h1>
        <p>Description</p>
        <p>Clicked: {this.state.clicked}</p>
      </div>
    )
  }
}

Mutating the state

A state should never be mutated by using

this.state.clicked = true

Instead, you should always use setState() instead, passing it an object:

this.setState({ clicked: true })

The object can contain a subset, or a superset, of the state. Only the properties you pass will be mutated, the ones omitted will be left in their current state.

Why you should always use setState()

The reason is that using this method, React knows that the state has changed. It will then start the serie of events that will lead to the Component being re-rendered, along with any DOM update.

State is encapsulated

A parent of a Component cannot tell if the child is stateful or stateless. Same goes for children of a Component.

Being stateful or stateless (functional or class-based) is entirely an implementation detail that other components don’t need to care about.

This leads us to Unidirectional Data Flow

Unidirectional Data Flow

A state is always owned by one Component. Any data that’s affected by this state can only affect Components below it: its children.

Changing a state on a Component will never affect its parent, or its siblings, or any other Component in the application: just its children.

This is the reason many times the state is moved up in the Components tree.

Moving the State Up in the Tree

Because of the Unidirectional Data Flow rules, if two components need to share a state, the state needs to be moved up to a common ancestor.

Many times the closest ancestor is the best place to manage the state, but it’s not a mandatory rule.

The state is passed down to the components that need that value via props:

class Converter extends React.Component {
  constructor(props) {
    super(props)
    this.state = { currency: '€' }
  }

  render() {
    return (
      <div>
        <Display currency={this.state.currency} />
        <CurrencySwitcher currency={this.state.currency} />
      </div>
    )
  }
}

The state can be mutated by a child component by passing a mutating function down as a prop:

class Converter extends React.Component {
  constructor(props) {
    super(props)
    this.state = { currency: '€' }
  }

  handleChangeCurrency = (event) => {
    this.setState({ currency: this.state.currency ===
      '€' ? '$' : '€' })
  }

  render() {
    return (
      <div>
        <Display currency={this.state.currency} />
        <CurrencySwitcher
          currency={this.state.currency}
          handleChangeCurrency={this.handleChangeCurrency} />
      </div>
    )
  }
}

const CurrencySwitcher = (props) => {
  return (
    <button onClick={props.handleChangeCurrency}>
      Current currency is {props.currency}. Change it!
    </button>
  )
}

const Display = (props) => {
  return (
    <p>Current currency is {props.currency}.</p>
  )
}

The result


Events

React provides an easy way to manage events. Prepare to say goodbye to addEventListener :)

In the previous article about the State you saw this example:

const CurrencySwitcher = (props) => {
  return (
    <button onClick={props.handleChangeCurrency}>
      Current currency is {props.currency}. Change it!
    </button>
  )
}

If you’ve been using JavaScript for a while, this is just like plain old JavaScript event handlers, except that this time you’re defining everything in JavaScript, not in your HTML, and you’re passing a function, not a string.

The actual event names are a little bit different because in React you use camelCase for everything, so onclick becomes onClick, onsubmit becomes onSubmit.

For reference, this is old school HTML with JavaScript events mixed in:

<button onclick="handleChangeCurrency()">
  ...
</button>

Event handlers

It’s a convention to have event handlers defined as methods on the Component class:

class Converter extends React.Component {
  handleChangeCurrency = (event) => {
    this.setState({ currency: this.state.currency ===
      '€' ? '$' : '€' })
  }
}

All handlers receive an event object that adheres, cross-browser, to the W3C UI Events spec.

Bind this in methods

Don’t forget to bind methods. The methods of ES6 classes by default are not bound. What this means is that this is not defined unless you define methods as

class Converter extends React.Component {
  handleClick = (e) => { /* ... */ }
  //...
}

when using the the property initializer syntax with Babel (enabled by default in create-react-app)

otherwise you need to bind it manually in the constructor:

class Converter extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(e) {}
}

The events reference

There are lots of events supported, here’s a summary list.

Clipboard

  • onCopy
  • onCut
  • onPaste

Composition

  • onCompositionEnd
  • onCompositionStart
  • onCompositionUpdate

Keyboard

  • onKeyDown
  • onKeyPress
  • onKeyUp

Focus

  • onFocus
  • onBlur

Form

  • onChange
  • onInput
  • onSubmit

Mouse

  • onClick
  • onContextMenu
  • onDoubleClick
  • onDrag
  • onDragEnd
  • onDragEnter
  • onDragExit
  • onDragLeave
  • onDragOver
  • onDragStart
  • onDrop
  • onMouseDown
  • onMouseEnter
  • onMouseLeave
  • onMouseMove
  • onMouseOut
  • onMouseOver
  • onMouseUp

Selection

  • onSelect

Touch

  • onTouchCancel
  • onTouchEnd
  • onTouchMove
  • onTouchStart

UI

  • onScroll

Mouse Wheel

  • onWheel

Media

  • onAbort
  • onCanPlay
  • onCanPlayThrough
  • onDurationChange
  • onEmptied
  • onEncrypted
  • onEnded
  • onError
  • onLoadedData
  • onLoadedMetadata
  • onLoadStart
  • onPause
  • onPlay
  • onPlaying
  • onProgress
  • onRateChange
  • onSeeked
  • onSeeking
  • onStalled
  • onSuspend
  • onTimeUpdate
  • onVolumeChange
  • onWaiting

Image

  • onLoad
  • onError

Animation

  • onAnimationStart
  • onAnimationEnd
  • onAnimationIteration

Transition

  • onTransitionEnd

React’s Declarative approach

You’ll run across articles describing React as a declarative approach to building UIs.

See declarative programming to read more about declarative programming.

React declarative approach

React made its “declarative approach” quite popular and upfront so it permeated the frontend world along with React.

It’s really not a new concept, but React took building UIs a lot more declarative than with HTML templates: you can build Web interfaces without even touching the DOM directly, you can have an event system without having to interact with the actual DOM Events.

For example looking up elements in the DOM using jQuery or DOM events is an iterative approach.

React’s declarative approach abstracts that for us. We just tell React we want a component to be rendered in a specific way, and we never have to interact with the DOM to reference it later.


The Virtual DOM

Many existing frameworks, before React came on the scene, were directly manipulating the DOM on every change.

The “real” DOM

What is the DOM, first: the DOM (Document Object Model) is a Tree representation of the page, starting from the <html> tag, going down into every children, called nodes.

It’s kept in the browser memory, and directly linked to what you see in a page. The DOM has an API that you can use to traverse it, access every single node, filter them, modify them.

The API is the familiar syntax you have likely seen many times, if you were not using the abstract API provided by jQuery and friends:

document.getElementById(id)
document.getElementsByTagName(name)
document.createElement(name)
parentNode.appendChild(node)
element.innerHTML
element.style.left
element.setAttribute()
element.getAttribute()
element.addEventListener()
window.content
window.onload
window.dump()
window.scrollTo()

React keeps a copy of the DOM representation, for what concernes the React rendering: the Virtual DOM

The Virtual DOM

Every time the DOM changes, the browser has to do two intensive operations: repaint (visual or content changes to an element that do not affect the layout and positioning relatively to other elements) and reflow (recalculate the layout of a portion of the page - or the whole page layout).

React uses a Virtual DOM to help the browser use less resources when changes need to be done on a page.

When you call setState() on a Component, specifying a state different than the previous one, React marks that Component as dirty. This is key: React only updates when a Component changes the state explicitly.

What happens next is:

  • React updates the Virtual DOM relative to the components marked as dirty (with some additional checks, like triggering shouldComponentUpdate())
  • Runs the diffing algorithm to reconciliate the changes
  • Updates the real DOM

Why is the Virtual DOM helpful: batching

The key thing is that React batches much of the changes and performs a unique update to the real DOM, by changing all the elements that need to be changed at the same time, so the repaint and reflow the browser must perform to render the changes are executed just once.