Component

A component is a small, reusable chunk of code that is responsible for one job. That job is often to render some HTML.

Hello world Component

Take a look at the code below. This code will create and render a new React component:

import React from ‘react’;
import ReactDOM from ‘react-dom’;

class MyComponentClass extends React.Component {
  render() {
    return <h1>Hello world</h1>;
  }
};

ReactDOM.render(
  <MyComponentClass />,
  document.getElementById(‘app’)
);

 

A lot of that code is probably unfamiliar. However you can recognize some JSX in there, as well as ReactDOM.render().

We are going to unpack that code, one small piece at a time. By the end of this lesson, you’ll understand how to build a React component!

Try on your computer

To run above code on your computer you need to install create-react-app package. Open Visual Studio Code, then from Terminal menu select New Terminal and enter this command:

 

$ npx create-react-app myapp

It takes a while to install create-react-app package and create a new react application in myapp folder. Go to this folder and run npm start.

$ cd myapp
$ npm start

Now your browser open at http://localhost:3000 and show react application.

 

Back to Visual Studio Code and from the File menu select Add folder to workspace and select myapp folder and open it. Then in the left sidebar click src folder and open index.js.  Replace content of this file with the code of MyComponentClass  from the previous section. Check your browser to see the result. You will see Hello World on the screen.

 

From now on, edit index.js and check the result in the browser.

Import React

Take a look at the code on line 1:

import React from ‘react’;

 

This line of code creates a new variable. That variable’s name is React, and its value is a particular, imported JavaScript object. This imported object contains methods that you need in order to use React. The object is called the React library.

Later, we’ll go over where the React library is imported from, and how the importing process works. For now, just know that you get the React library via import React from ‘react’;.

You’ve already seen one of the methods contained in the React library: React.createElement(). Recall that when a JSX element is compiled, it transforms into a React.createElement() call.

For this reason, you have to import the React library, and save it in a variable named React, before you can use any JSX at all.React.createElement() must be available in order for JSX to work.

Import ReactDOM

Now take a look at the code on line 2:

import ReactDOM from ‘react-dom’;

 

This line of code is very similar to line 1.

Lines 1 and 2 both import JavaScript objects. In both lines, the imported object contains React-related methods.

However, there is a difference!

The methods imported from ‘react-dom’ are meant for interacting with the DOM. You are already familiar with one of them: ReactDOM.render().

The methods imported from ‘react’ don’t deal with the DOM at all. They don’t engage directly with anything that isn’t part of React.

To clarify: the DOM is used in React applications, but it isn’t part of React. After all, the DOM is also used in countless non-React applications. Methods imported from ‘react’ are only for pure React purposes, such as creating components or writing JSX elements.

Create Component Class

You’ve learned that a React component is a small, reusable chunk of code that is responsible for one job, which often involves rendering HTML.

Here’s another fact about components: every component must come from a component class.

A component class is like a factory that creates components. If you have a component class, then you can use that class to produce as many components as you want.

To make a component class, you use a base class from the React library:React.Component.

What is React.Component, and how do you use it to make a component class?

React.Component is a JavaScript class. To create your own component class, you must subclass React.Component. You can do this by using the syntax class YourComponentNameGoesHere extends React.Component {}.

JavaScript classes and subclassing are a complex topic beyond the scope of this course. If you aren’t comfortable with them, read JavaScript eBook.

Look at the code below. A lot it is still unfamiliar, but you can understand more than you could before!

import React from ‘react’;
import ReactDOM from ‘react-dom’;

class MyComponentClass extends React.Component {
  render() {
    return <h1>Hello world</h1>;
  }
}

ReactDOM.render(
<MyComponentClass />,
document.getElementById(‘app’)
);

 

On line 4, you know that you are declaring a new component class, which is like a factory for building React components. You know that React.Component is a class, which you must subclass in order to create a component class of your own. You also know that React.Component is a property on the object which was returned by import React from ‘react’ on line 1.

Name Component Class

Good! Subclassing React.Component is the way to declare a new component class.

When you declare a new component class, you need to give that component class a name. On line 4, notice that our component class’s name is MyComponentClass.

Component class variable names must begin with capital letters!

This adheres to JavaScript’s class syntax. It also adheres to a broader programming convention in which class names are written in UpperCamelCase.

In addition, there is a React-specific reason why component class names must always be capitalized. We’ll get to that soon!

Component Class Instructions

Let’s review what you’ve learned so far! Find each of these points in the above code:

  • On line 1, import React from ‘react’ creates a JavaScript object. This object contains properties that are needed to make React work, such as React.createElement() and React.Component.
  • On line 2, import ReactDOM from ‘react-dom’ creates another JavaScript object. This object contains methods that help React interact with the DOM, such as ReactDOM.render().
  • On line 4, by subclassing React.Component, you create a new component class. This is not a component! A component class is more like a factory that produces components. When you start making components, each one will come from a component class.
  • Whenever you create a component class, you need to give that component class a name. That name should be written in UpperCamelCase. In this case, your chosen name is MyComponentClass.

Something that we haven’t talked about yet is the body of your component class: the pair of curly braces after React.Component, and all of the code between the curly braces.

Like all JavaScript classes, this one needs a body. The body will act as a set of instructions, explaining to your component class how it should build a React component.

Here’s what your class body would look like on its own, without the rest of the class declaration syntax.

{
  render() {
    return <h1>Hello world</h1>;
  }
}

That doesn’t look like a set of instructions explaining how to build a React component! Yet that’s exactly what it is.

The Render Function

A component class is like a factory that builds components. It builds these components by consulting a set of instructions, which you must provide. Let’s talk about these instructions!

For starters, these instructions should take the form of a class declaration body. That means that they will be delimited by curly braces, like this:

class ComponentFactory extends React.Component {
    // instructions go here, between the curly braces
}

 

The instructions should be written in typical JavaScript ES2015 class syntax.

There is only one property that you have to include in your instructions: a render method.

A render method is a property whose name is render, and whose valueis a function. The term “render method” can refer to the entire property, or to just the function part.

class ComponentFactory extends React.Component {
  render() {}
}

 

A render method must contain a return statement. Usually, this return statement returns a JSX expression:

class ComponentFactory extends React.Component {
  render() {
    return <h1>Hello world</h1>;
  }
}

 

Of course, none of this explains the point of a render method. All you know so far is that its name is render, it needs a return statement for some reason, and you have to include it in the body of your component class declaration. We’ll get to the ‘why’ of it soon!

Creating Component Instance

MyComponentClass is now a working component class! It’s ready to follow its instructions and make some React components.

So, let’s make a React component! It only takes one more line:

<MyComponentClass />

 

To make a React component, you write a JSX element. Instead of naming your JSX element something like h1 or div like you’ve done before, give it the same name as a component class. Voilà, there’s your component instance!

JSX elements can be either HTML-like, or component instances. JSX uses capitalization to distinguish between the two! That is the React-specific reason why component class names must begin with capital letters. In a JSX element, that capitalized first letter says, “I will be a component instance and not an HTML tag.”

Rendering Component

You have learned that a component class needs a set of instructions, which tell the component class how to build components. When you make a new component class, these instructions are the body of your class declaration:

class MyComponentClass extends React.Component
{ // everything in between these curly-braces is instructions for how to build components

  render() {
    return <h1>Hello world</h1>;
  }
}

 

This class declaration results in a new component class, in this case named MyComponentClass. MyComponentClass has one method, named render. This all happens via standard JavaScript class syntax.

You haven’t learned how these instructions actually work to make components! When you make a component by using the expression <MyComponentClass />, what do these instructions do?

Whenever you make a component, that component inherits all of the methods of its component class. MyComponentClass has one method: MyComponentClass.render(). Therefore, <MyComponentClass /> also has a method named render.

You could make a million different <MyComponentClass /> instances, and each one would inherit this same exact render method.

In order to render a component, that component needs to have a method named render. Your component has this! It inherited a method named render from MyComponentClass.

Since your component has a render method, all that’s left to do is call it. This happens in a slightly unusual way.

To call a component’s render method, you pass that component to ReactDOM.render(). Notice your component, being passed as ReactDOM.render()‘s first argument:

ReactDOM.render(
  <MyComponentClass />,
  document.getElementById(‘app’)
);

ReactDOM.render() will tell <MyComponentClass /> to call its render method.

<MyComponentClass /> will call its render method, which will return the JSX element <h1>Hello world</h1>. ReactDOM.render() will then take that resulting JSX element, and add it to the virtual DOM. This will make “Hello world” appear on the screen.

Use Multiline JSX in a Component

In this lesson, you will learn some common ways that JSX and React components work together. You’ll get more comfortable with both JSX and components, while picking up some new tricks.

Take a look at this HTML:

<blockquote>
  <p>
    The world is full of objects, more or less interesting; I do not wish to add any more.
  </p>
  <cite>
    <a target=“_blank”
      href=“https://en.wikipedia.org/wiki/Douglas_Huebler”>
      Douglas Huebler
    </a>
  </cite>
</blockquote>

 

How might you make a React component that renders this HTML?

Check this code to see one way of doing it.

import React from ‘react’;
import ReactDOM from ‘react-dom’;

class QuoteMaker extends React.Component {
  render() {
    return (
      <blockquote>
        <p>
          The world is full of objects, more or less interesting; I do not wish to add any more.
        </p>
        <cite>
          <a target=“_blank”
            href=“https://en.wikipedia.org/wiki/Douglas_Huebler”>
            Douglas Huebler
          </a>
        </cite>
      </blockquote>
    );
  }
};

ReactDOM.render(
  <QuoteMaker />,
  document.getElementById(‘app’)
);

 

The key thing to notice in QuoteMaker is the parentheses in the return statement, on lines 6 and 18. Until now, your render function return statements have looked like this, without any parentheses:

return <h1>Hello world</h1>;

 

However, a multi-line JSX expression should always be wrapped in parentheses! That is why QuoteMaker‘s return statement has parentheses around it.

Use Variable Attribute In Component

Take a look at this JavaScript object named redPanda:

const redPanda = {
  src:  ‘https://upload.wikimedia.org/wikipedia/commons/b/b2/Endangered_Red_Panda.jpg’,
  alt: ‘Red Panda’,
  width:  ‘200px
};

 

How could you render a React component, and get a picture with redPanda‘s properties?

Check this code to see one way to do it.

import React from ‘react’;
import ReactDOM from ‘react-dom’;

const redPanda = {
  src: ‘https://upload.wikimedia.org/wikipedia/commons/b/b2/Endangered_Red_Panda.jpg’,
  alt: ‘Red Panda’,
  width:  ‘200px’
};

class RedPanda extends React.Component {
  render() {
    return (
      <div>
        <h1>Cute Red Panda</h1>
        <img
          src={redPanda.src}
          alt={redPanda.alt}
          width={redPanda.width} />
      </div>
    );
  }
}

ReactDOM.render(
  <RedPanda />,
  document.getElementById(‘app’)
);

 

Note all of the curly-brace JavaScript injections inside of the render function! Lines 16, 17, and 18 all use JavaScript injections.

You can, and often will, inject JavaScript into JSX inside of a render function.

Put Logic In Render Function

A render() function must have a return statement. However, that isn’t all that it can have.

A render() function can also be a fine place to put simple calculations that need to happen right before a component renders. Here’s an example of some calculations inside of a render function:

class Random extends React.Component {
  render() {
    // First, some logic that must happen
    // before rendering:
    const n = Math.floor(Math.random() * 10 + 1);
    // Next, a return statement
    // using that logic:
    return <h1>The number is {n}!</h1>;
  }
}

 

Watch out for this common mistake:

class Random extends React.Component {
  // This should be in the render function:
  const n = Math.floor(Math.random() * 10 + 1);

  render() {
    return <h1>The number is {n}!</h1>;
  }
};

 

In the above example, the line with the const n declaration will cause a syntax error, as is it should not be part of the class declaration itself, but should occur in a method like render().

Use Conditionals in Render Function

How might you use a conditional statement inside of a render()function?

Check this code to see one way of doing it.

import React from ‘react’;
import ReactDOM from ‘react-dom’;

class TodaysPlan extends React.Component {
  render() {
    let task;
    if (!apocalypse) {
      task = ‘learn React.js’
    } else {
      task = ‘run around’
    }

    return <h1>Today I am going to {task}!</h1>;
  }
}

ReactDOM.render(
<TodaysPlan />,
document.getElementById(‘app’)
);

 

Notice that the if statement is located inside of the render function, but before the return statement. This is pretty much the only way that you will ever see an if statement used in a render function.

Use this In Component

The word this gets used in React a lot!

You are especially likely to see this inside of the body of a component class declaration. Here’s an example:

class IceCreamGuy extends React.Component {
  get food() {
    return ‘ice cream’;
  }

  render() {
    return <h1>I like {this.food}.</h1>;
  }
}

 

In the code, what does this mean?

The simple answer is that this refers to an instance of IceCreamGuy. The less simple answer is that this refers to the object on which this‘s enclosing method, in this case .render(), is called. It is almost inevitable that this object will be an instance of IceCreamGuy, but technically it could be something else.

Let’s assume that this refers to an instance of your component class, as will be the case in all the examples in this course. IceCreamGuy has two methods: .food and .render(). Since this will evaluate to an instance of IceCreamGuy, this.food will evaluate to a call of IceCreamGuy‘s .food method. This method will, in turn, evaluate to the string “ice cream.”

Why don’t you need parentheses after this.food? Shouldn’t it be this.food()?

You don’t need those parentheses because .food is a getter method. You can tell this from the get in the above class declaration body.

There’s nothing React-specific about getter methods, nor about this behaving in this way! However, in React you will see this used in this way almost constantly.

this in JavaScript can be a difficult concept! Here is a good resource for understanding this in JavaScript.

Event Listener In Component

Render functions often contain event listeners. Here’s an example of an event listener in a render function:

render() {
  return (
    <div onHover={myFunc}>
    </div>
  );
}

 

Recall that an event handler is a function that gets called in response to an event. In the above example, the event handler is myFunc().

In React, you define event handlers as methods on a component class. Like this:

class MyClass extends React.Component {
  myFunc() {
    alert(‘Stop it.  Stop hovering.’);
  }

  render() {
    return (
      <div onHover={this.myFunc}>
      </div>
    );
  }
}

 

Notice that the component class has two methods: .myFunc() and .render(). .myFunc() is being used as an event handler. .myFunc() will be called any time that a user hovers over the rendered <div></div>.

Components Interact

A React application can contain dozens, or even hundreds, of components.

Each component might be small and relatively unremarkable on its own. When combined, however, they can form enormous, fantastically complex ecosystems of information.

In other words, React apps are made out of components, but what makes React special isn’t components themselves. What makes React special is the ways in which components interact.

This unit is an introduction to components interacting.

A Component in a Render Function

Here is a .render() method that returns an HTML-like JSX element:

class Example extends React.Component {
  render() {
    return <h1>Hello world</h1>;
  }
}

 

You’ve seen render methods return <div></div>s, <p></p>s, and <h1></h1>s, just like in the above example.

Render methods can also return another kind of JSX: component instances.

class OMG extends React.Component {
  render() {
    return <h1>Whooaa!</h1>;
  }
}

class Crazy extends React.Component {
  render() {
    return <OMG />;
  }
}

 

In the above example, Crazy‘s render method returns an instance of the OMG component class. You could say that Crazy renders an <OMG />.

 

This is new territory! You’ve never seen a component rendered by another component before.

You have seen a component rendered before, though, but not by another component. Instead, you’ve seen a component rendered by ReactDOM.render().

When a component renders another component, what happens is very similar to what happens when ReactDOM.render() renders a component.

Require A File

When you use React.js, every JavaScript file in your application is invisible to every other JavaScript file by default. ProfilePage.js and NavBar.js can’t see each other.

This is a problem!

// ProfilePage.js

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { NavBar } from ‘./NavBar’;

class ProfilePage extends React.Component {
  render() {
    return (
      <div>
<NavBar />
        <h1>All About Me!</h1>
        <p>I like movies and blah blah blah blah blah</p>
        <img src=“https://s3-us-west-2.amazonaws.com/s.cdpn.io/210284/93.jpg” />
      </div>
    );
  }
}

ReactDOM.render(<ProfilePage />, document.getElementById(‘app’));

 

// NavBar.js
import React from ‘react’;

export class NavBar extends React.Component {
  render() {
    const pages = [‘home’, ‘blog’, ‘pics’, ‘bio’, ‘art’, ‘shop’, ‘about’, ‘contact’];
    const navLinks = pages.map(page => {
      return (
        <a href={‘/’ + page}>
          {page}
        </a>
      )
    });

    return <nav>{navLinks}</nav>;
  }
}

 

On line 9, you just added an instance of the NavBar component class. But since you’re in ProfilePage.js, JavaScript has no idea what NavBarmeans.

If you want to use a variable that is declared in a different file, such as NavBar, then you have to import the variable that you want. To import a variable, you can use an import statement:

import { NavBar } from ‘./NavBar.js’;

 

We’ve used import before, but not like this! Notice the differences between the above line of code and this familiar line:

import React from ‘react’;

 

The first important difference is the curly braces around NavBar. We’ll get to those soon!

The second important difference involves the contents of the string at the end of the statement: ‘react’ vs ‘./NavBar.js’.

If you use an import statement, and the string at the end begins with either a dot or a slash, then import will treat that string as a filepath.import will follow that filepath, and import the file that it finds.

If your filepath doesn’t have a file extension, then “.js” is assumed. So the above example could be shortened:

import { NavBar } from ‘./NavBar’;

 

One final, important note:

None of this behavior is specific to React! Module systems of independent, importable files are a very popular way to organize code.React’s specific module system comes from ES6. More on all of that later.

export

Alright! You’ve learned how to use import to grab a variable from a file other than the file that is currently executing.

When you import a variable from a file that is not the current file, then an import statement isn’t quite enough. You also need an export statement, written in the other file, exporting the variable that you hope to grab.

export comes from ES6’s module system, just like import does. export and import are meant to be used together, and you rarely see one without the other.

There are a few different ways to use export. In this course, we will be using a style called “named exports.” Here’s how named exports works:

In one file, place the keyword export immediately before something that you want to export. That something can be any top-level var, let, const, function, or class:

// Manifestos.js:

export const faveManifestos = {
  futurist: ‘http://www.artype.de/Sammlung/pdf/russolo_noise.pdf’,
  agile: ‘https://agilemanifesto.org/iso/en/manifesto.html’,
  cyborg:   ‘http://faculty.georgetown.edu/irvinem/theory/Haraway-CyborgManifesto-1.pdf’
};

 

You can export multiple things from the same file:

// Manifestos.js:

export const faveManifestos = {
  futurist: ‘http://www.artype.de/Sammlung/pdf/russolo_noise.pdf’,
  agile:  ‘https://agilemanifesto.org/iso/en/manifesto.html’,
  cyborg:   ‘http://faculty.georgetown.edu/irvinem/theory/Haraway-CyborgManifesto-1.pdf’
};

export const alsoRan = ‘TimeCube’;

 

In a different file, import the name of the var, let, const, function, or class from the first file:

// App.js:

// Import faveManifestos and alsoRan from ./Manifestos.js:
import { faveManifestos, alsoRan } from ‘./Manifestos’;

// Use faveManifestos:
console.log(`A Cyborg Manifesto:  ${faveManifestos.cyborg}`);

 

This style of importing and exporting in JavaScript is known as “named exports.” When you use named exports, you always need to wrap your imported names in curly braces, such as:

import { faveManifestos, alsoRan } from ‘./Manifestos’;`

 

JavaScript’s ES6 module system goes beyond named exports and has several advanced syntax features.

Component Rendering In Action

Now you’re ready for <ProfilePage /> to render <NavBar />!

All that’s left to do is render <ProfilePage />.

import React from ‘react’;
import ReactDOM from ‘react-dom’;
import { NavBar } from ‘./NavBar’;

class ProfilePage extends React.Component {
  render() {
    return (
      <div>
<NavBar />
        <h1>All About Me!</h1>
        <p>I like movies and blah blah blah blah blah</p>
        <img src=“https://s3-us-west-2.amazonaws.com/s.cdpn.io/210284/93.jpg” />
      </div>
    );
  }
}

ReactDOM.render(<ProfilePage />, document.getElementById(‘app’));

Review

Congratulations! You have finished the unit on React components.

React components are complicated. Their syntax is complicated, and the reasoning behind their syntax is especially complicated.

You have learned a lot about both their syntax and their reasoning. You have learned about component classes and component instances. You have learned about React.Component, and about the instructions that you must provide to a component class. You have learned how to import, and how to render a component instance.

You have been introduced to some common ways of using JSX in React components. You have rendered components using multiline JSX expressions, logic inside of the render function, a conditional statement, this, and an event listener.

You have spent a lot of time studying React components in isolation! Now, it’s time to start learning how components fit into with the world around them.