Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
React Components

You're reading from   React Components Explore the power of React components for cutting-edge web development

Arrow left icon
Product type Paperback
Published in Apr 2016
Publisher
ISBN-13 9781785889288
Length 182 pages
Edition 1st Edition
Tools
Arrow right icon
Author (1):
Arrow left icon
Christopher Pitt Christopher Pitt
Author Profile Icon Christopher Pitt
Christopher Pitt
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

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:

Using modern JavaScript
You have been reading a chapter from
React Components
Published in: Apr 2016
Publisher:
ISBN-13: 9781785889288
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime