Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
React Components
React Components

React Components: Explore the power of React components for cutting-edge web development

By Christopher Pitt
€22.99 €15.99
Book Apr 2016 182 pages 1st Edition
eBook
€22.99 €15.99
Print
€28.99
Subscription
€14.99 Monthly
eBook
€22.99 €15.99
Print
€28.99
Subscription
€14.99 Monthly

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
Buy Now

Product Details


Publication date : Apr 21, 2016
Length 182 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781785889288
Vendor :
Facebook
Category :
Table of content icon View table of contents Preview book icon Preview Book

React Components

Chapter 1. Thinking in Components

React was the first interface library that got me thinking about component-based design. React promotes many good patterns and habits, but this one stands out for me. To understand why, we need to think about how React works under the hood. React is primarily a rendering engine. It was created (and is used) for generating user interfaces.

How interfaces used to work (and indeed still work apart from React) was that someone would come up with a design. That image file would then be split up into assets for each interactive part of the interface. A library such as jQuery would manage user interactions and connect different interface components, often with an assortment of plugins.

Individual interface components can be quite clean and complete individually. However, when they are combined, interactions between components and shared, mutable component state often make a messy codebase. One of the main reasons why React was created was to simplify the interactions between components, so they can remain clean and easy to understand.

Why components?


Component-based design is powerful, especially when we use immutable data and unidirectional data flow. It forces me to stop thinking about how different technologies or tools interact. It gets me thinking about the single most important function of each interface element.

When we start building an application, it's tempting to think of every piece as part of the whole. All interface elements blend into the same big picture, until it becomes so big that separating parts of it out seems impossible.

Imagine you had to build a space ship. What a huge task! You'd need some rocket boosters, a couple of wings, life support, and so on. Now consider how you would approach it if one of the constraints was that each moving part of the space ship would need to be individually tested.

Testing is the great divide between designing systems as a whole and designing systems as large collections of small pieces. Component-based design is fantastic because it makes sure that every part is testable.

Using modern JavaScript


React components are wonderfully encapsulated. Each component is a blueprint for what a focused bit of markup should look like at any moment. They're reusable and can change their behavior depending on the context provided. Does that remind you of another programming paradigm?

Let's talk about JavaScript. JavaScript has a prototypical inheritance model. That means different objects can have a common structure. The structure of one object can be derived from the structure of another.

It also means that changes to the original object are inherited in all derivative objects. Let me illustrate this with some code:

var Page = function(content) {
    this.content = content;
};

Page.prototype.render = function() {
    return "<div>" + this.content + "</div>";
}

var Post = function(tags, content) {
    this.tags = tags;

    Page.call(this, content);
};

Post.prototype = new Page();

Post.prototype.render = function() {
    var page = Page.prototype.render.call(this);

    return "<ul>" + this.renderTags() + "</ul>" + page;
};

Post.prototype.renderTags = function() {
    return "<li>" + this.tags.join("</li></li>") + "</li>";
};

var page = new Page("Welcome to my site!");
var post = new Post(["news"], "A new product!");

Page.prototype.render = function() {
    return "<section>" + this.content + "</section>";
};

I begin by creating a function called Page, which requires a content parameter. A simple render method returns that content, wrapped in a div tag. This seems like a good starting point for a website.

Next, I decide to make a second type called Post. Objects of this type have tags, so I create a new initialization function to store them. I want Post to behave almost like a Page type, so I call the Page initialization function.

To inherit the Page methods in Post, I need to link their prototypes. I can then choose to override the render method and add new methods to the derived type. I can also change the Page type and these changes will be inherited by objects of the Post type. The connection happens because a prototype is a reference and not a copy.

Depending on the programming languages you grew up with, prototypical inheritance might be tricky at first. Many new developers learn (incorrectly) that object-oriented code means class-oriented code. Dynamic concepts such as prototypes are foreign to them. In the past, this led to a few libraries implementing "pretend" classes. They created patterns that would make code appear as if it was class-oriented.

Then, ES6 added the class keyword. It's a formalization of the pattern I just showed you. It's a syntactic shortcut to prototypical inheritance.

We could reduce the previous code to:

class Page {
    constructor(content) {
        this.content = content;
    }

    render() {
        return "<div>" + this.content + "</div>";
    }
}

class Post extends Page {
    constructor(tags, content) {
        super(content);
        this.tags = tags;
    }

    render() {
        var page = super.render();
        
        return "<ul>" + this.renderTags() + "</ul>" + page;
    }

    renderTags() {
        return "<li>" + this.tags.join("</li></li>") + "</li>";
    }
}

var page = new Page("Welcome to my site!");
var post = new Post(["news"], "A new product!");

Note

If you're trying to run this using Node (preferably a version greater than 4.1), you may need to add use strict at the top of the file.

Notice how much clearer things are? If you want to use classes, then this syntactic shortcut is brilliant!

Let's look at a typical ES5-compatible React component:

var Page = React.createClass({
    render: function() {
        return <div>{this.props.content}</div>;
    }
});

var Post = React.createClass({
    render: function() {
        var page = <Page content={this.props.content} />
        var tags = this.renderTags();

        return <div><ul>{tags}</ul>{page}</div>;
    },
    renderTags: function() {
        return this.props.tags.map(function(tag, i) {
            return <li key={i}>{tag}</li>;
        });
    }
});

ReactDOM.render(
    <Post tags={["news"]} content="A new product!" />,
    document.querySelector(".react")
);

You've probably seen this kind of code before. It's called JSX and it's a JavaScript superset language. The idea is that the markup and the supporting logic are created and stored together.

Note

React components must return a single React node, which is why we wrap the tags and page elements in a div element. If you are using React in the browser, you also need to render your components to an existing DOM node (like I've just rendered the post to .react).

We'll get into some of the specifics in later chapters, but this is doing pretty much the same thing as before. We create a base component called Page. It renders a property instead of a constructor parameter.

The Post component composes the Page component. This style of React code doesn't support component inheritance. For that, we need ES6 code:

class Page extends React.Component {
    render() {
        return <div>{this.props.content}</div>;
    }
}

class Post extends Page {
    render() {
        var page = super.render();
        var tags = this.renderTags();

        return <div><ul>{tags}</ul>{page}</div>;
    }

    renderTags() {
        return this.props.tags.map(function(tag, i) {
            return <li key={i}>{tag}</li>;
        });
    }
}

We could still compose Page within Post, but that's not the only option with ES6. This code resembles the non-React version we saw earlier.

In upcoming chapters, we'll learn many useful features of ES6 that'll allow us to create modern, expressive React components.

Note

If you want to look ahead a little, check out http://babeljs.io/docs/learn-es2015. It's a great place to learn the main features of ES6!

Babel is the cross-compilation tool we'll use to turn ES6 code into ES5 code:

Compiling modern JavaScript


It's time for us to look at how to compile ES6 and JSX code into formats that most browsers can read. Create a folder for your React components and run the following commands inside it:

$ npm init
$ npm install --save browserify babelify
$ npm install --save react react-dom

The first command will kick off a series of questions, most of which should have reasonable defaults. The second command will download a builder and a cross-compiler for your ES6 code. Place the following component in a file called page.js:

import React from "react";

export default class Page extends React.Component {
    render() {
        return <div>{this.props.content}</div>;
    }
}

There are a couple of important differences between this and the previous Page component. We import the main React object from within the node_modules folder. We also export the class definition so that importing this file immediately references this class. It's a good idea to limit each file to a single class. It's also a good idea to make each file define types or use them. We use this class in main.js:

import React from "react";
import ReactDOM from "react-dom";
import Page from "./page";

ReactDOM.render(
    <Page content="Welcome to my site!" />,
    document.querySelector(".react")
);

This code imports React and ReactDOM from within the node_modules folder, so we can render the Page class. Here we're referencing an element in the DOM again. We can use this JavaScript within an HTML page:

<!doctype html>
<html lang="en">
    <body>
        <div class="react"></div>
    </body>
    <script src="main.dist.js"></script>
</html>

The final step is to compile the ES6/JSX code in main.js to ES5-compatible code in main.dist.js:

$ alias browserify=node_modules/.bin/browserify
$ browserify -t babelify main.js -o main.dist.js

The first command creates a shortcut to the browserify command in the node_modules/.bin folder. This is useful for repeated calls to browserify.

Note

If you want to keep that alias around, be sure to add it to your ~/.bashrc, ~/.zshrc or ~/.profile file.

The second command starts a build. Browserify will combine all imported files into a single file, so they can be used in a browser.

We use the babelify transformer, so the ES6 code becomes ES5-compatible code. Babel supports JSX, so we don't need additional steps for that. We specify main.js as the file to transform and main.dist.js as the output file.

Note

If you want to compile React and ReactDOM into their own file, you can exclude them with the -x switch. Your command should be something like this:

browserify main.js -t babelify -x react -x react-dom --outfile main.dist.js

Debugging in the browser


We can also use our code directly in the browser. There may be times when we want to see the effects of a change, without a build step. In such cases, we can try something like this:

$ npm install --save babel-core
$ npm install --save systemjs

These will give us access to a browser-based dependency manager and cross-compiler; that is, we can use unbundled source code in an example HTML file:

<!DOCTYPE html>
<html>
    <head>
        <script src="/node_modules/babel-core/browser.js"></script>
        <script src="/node_modules/systemjs/dist/system.js"></script>
    </head>
    <body>
        <div class="react"></div>
        <script>
            System.config({
                "transpiler": "babel",
                "map": {
                    "react": "/examples/react/react",
                    "react-dom": "/examples/react/react-dom",
                    "page": "/src/page"
                },
                "defaultJSExtensions": true
            });

            System.import("main");
        </script>
    </body>
</html>

This uses the same unprocessed main.js file as before, but we no longer need to rebuild it after each change to the source code. The System is a reference to the SystemJS library we just installed through NPM. It takes care of the import statements, loading those dependencies with Ajax requests.

You may notice the references to react and react-dom. We import these in main.js, but where do they come from? Browserify fetches them out of the node_modules folder. When we skip the Browserify step, we need to let SystemJS know where to find them.

The easiest place to find these files is at https://facebook.github.io/react. Click on the download button, extract the archive, and copy the JS files in the build folder to where they are referenced in the HTML page.

The ReactJS website is a great place to download ReactJS, and find documentation about how you can use it:

Managing common tasks


As our collection of React components grows, we'll need ways of bundling them all together. It would also be a good idea for us to minify the resulting JavaScript to reduce the time it takes to load them in a browser.

We can perform these kinds of tasks using scripts in package.json:

"scripts": {
    "bundle": "browserify -t babelify main.js -o main.dist.js",
    "minify": "..."
}

NPM scripts are fine for small, simple tasks. When the tasks get more complex, we'll start to see the drawbacks of using NPM scripts for this. There's no easy way to use variables in these scripts, so parameters are often repeated. The scripts are also a bit inflexible and frankly ugly.

There are a few tools that address these problems. We're going to use one of them, called Grunt, to create flexible, repeatable tasks.

The Grunt website has instructions for using Grunt and a list of popular plugins you can use to customize your workflow:

Grunt is a JavaScript task runner. There are three steps for using it:

  1. First, we need to install the CLI tool. We'll use this to run different tasks.

  2. Then, we need to install the libraries our tasks will use, via NPM.

  3. Finally, we need to create a gruntfile.js file where we'll put our tasks.

We can install the CLI tool using the following command:

$ npm install -g grunt-cli

Note

The preceding command installs the Grunt CLI tool globally. If you don't want that, omit the -g flag. You'll need to alias/run it directly with node_modules/.bin/grunt from here on though.

We will need the following task libraries:

$ npm install --save-dev grunt
$ npm install --save-dev grunt-browserify
$ npm install --save-dev grunt-contrib-uglify
$ npm install --save-dev grunt-contrib-watch

The global CLI tool needs a local copy of grunt. In addition, we also want the glue libraries to run Browserify, Uglify, and a file watcher in Grunt. We configure them with something like this:

module.exports = function(grunt) {
    grunt.initConfig({
        "browserify": {
            "main.js": ["main.es5.js"],
            "options": {
                "transform": [
                    "babelify"
                ],
                "external": [
                    "react", "react-dom"
                ]
            }
        },
        "uglify": {
            "main.es5.js": ["main.dist.js"]
        },
        "watch": {
            "files": ["main.js"],
            "tasks": ["browserify", "uglify"]
        }
    });

    grunt.loadNpmTasks("grunt-browserify");
    grunt.loadNpmTasks("grunt-contrib-uglify");
    grunt.loadNpmTasks("grunt-contrib-watch");

    grunt.registerTask("default", ["browserify", "uglify"]);
};

We can configure each task in gruntfile.js. Here, we create a browserify task, defining the source and destination files. We include the babelify transformation to convert our ES6 classes into ES5-compatible code.

Note

I've added the external option so you can see how. If you don't need it, just delete it and your bundle file should then include the full React source code.

After the ES6 code is transformed, we can run Uglify to remove unnecessary whitespace. This reduces the size of the file, so browsers can download it quicker. We can target the file Browserify created and create a new minified file from it.

Finally, we create a watch task. This watches for changes to main.js and triggers the Browserify and Uglify tasks. We need to register a default set of tasks, which we set to browserify and uglify. This configuration enables the following commands:

$ grunt
$ grunt browserify
$ grunt uglify
$ grunt watch

There are other great tools like Grunt:

They work with similar configuration files, but the configuration is done through functional composition. The important thing to take from this is that there are tools we can use to automate tasks we would have run by hand. They make these repetitive tasks easy!

Testing in JSBin


If you're anything like me, you'll often just want a quick place to test some small component or ES6 code. Setting up these build chains or live browser environments takes time. There is a quicker way. It's called JSBin and you can find it at https://jsbin.com:

To get the most out of JSBin, be sure to set the JavaScript dropdown to ES6/Babel and include the ReactJS scripts from CDNJS. These are pre-built versions of ReactJS, so you can create React components (using ES6 features) straight from the browser.

Tip

Downloading the example code

You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

You can download the code files by following these steps:

  • Log in or register to our website using your e-mail address and password.

  • Hover the mouse pointer on the SUPPORT tab at the top.

  • Click on Code Downloads & Errata.

  • Enter the name of the book in the Search box.

  • Select the book for which you're looking to download the code files.

  • Choose from the drop-down menu where you purchased this book from.

  • Click on Code Download.

You can also download the code files by clicking on the Code Files button on the book's webpage at the Packt Publishing website. This page can be accessed by entering the book's name in the Search box. Please note that you need to be logged in to your Packt account.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

  • WinRAR / 7-Zip for Windows

  • Zipeg / iZip / UnRarX for Mac

  • 7-Zip / PeaZip for Linux

Summary


In this chapter, we saw why component-based design is good. We saw what simple React components look like. We saw a few interesting differences between ES5 and ES6, and we also saw how those differences influence React components.

We also saw a few ways to make ES6 code work in an ES5-compatible way. We can write cutting-edge code that works on common browsers. We can even bundle that code into single, efficient files, or debug it live in a browser.

In the next chapter, we're going to look at some intricacies of state and properties. We'll begin by creating reusable React components to use in our example application.

Left arrow icon Right arrow icon

Key benefits

  • Learn to build better websites by creating a variety of different components in React
  • Conceptualize the design and build maintainable web apps with the help of components
  • A fast-paced guide to help you learn about component-based development in React

Description

The reader will learn how to use React and its component-based architecture in order to develop modern user interfaces. A new holistic way of thinking about UI development will establish throughout this book and the reader will discover the power of React components with many examples. After reading the book and following the example application, the reader has built a small to a mid-size application with React using a component based UI architecture. The book will take the reader through a journey to discover the benefits of component-based user interfaces over the classical MVC architecture. Throughout the book, the reader will develop a wide range of components and then bring them together to build a component-based UI. By the end of this book, readers would have learned several techniques to build powerful components and how the component-based development is beneficial over regular web development.

What you will learn

[*] How to structure an app into components Working with nested components [*] Work with nested components [*] Set up communication across components [*] Style the existing components [*] Work with Material Design as a component [*] Render components on the server [*] Make the best of design patterns [*] Make the app pluggable

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
Buy Now

Product Details


Publication date : Apr 21, 2016
Length 182 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781785889288
Vendor :
Facebook
Category :

Table of Contents

17 Chapters
React Components Chevron down icon Chevron up icon
Credits Chevron down icon Chevron up icon
About the Author Chevron down icon Chevron up icon
About the Reviewer Chevron down icon Chevron up icon
www.PacktPub.com Chevron down icon Chevron up icon
Preface Chevron down icon Chevron up icon
Thinking in Components Chevron down icon Chevron up icon
Working with Properties and State Chevron down icon Chevron up icon
Saving and Communicating Data Chevron down icon Chevron up icon
Styling and Animating Components Chevron down icon Chevron up icon
Going Material! Chevron down icon Chevron up icon
Changing Views Chevron down icon Chevron up icon
Rendering on the Server Chevron down icon Chevron up icon
React Design Patterns Chevron down icon Chevron up icon
Thinking of Plugins Chevron down icon Chevron up icon
Testing Components Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Filter icon Filter
Top Reviews
Rating distribution
Empty star icon Empty star icon Empty star icon Empty star icon Empty star icon 0
(0 Ratings)
5 star 0%
4 star 0%
3 star 0%
2 star 0%
1 star 0%

Filter reviews by


No reviews found
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.