This post is part of the series 30 Days of React.

In this series, we're starting from the very basics and walk through everything you need to know to get started with React. If you've ever wanted to learn React, this is the place to start!

Our First Components

Edit this page on Github

The first two articles in this series were heavy on discussion. In today's session, let's dive into some code and write our first React app.

Let's revisit the "Hello world" app we introduced on day one. Here it is again, written slightly differently:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello world</title>
  <!-- Script tags including React -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
  <div id="app"></div>
  <script type="text/babel">
    var app = <h1>Hello world</h1>
    var mountComponent = document.querySelector('#app');
    ReactDOM.render(app, mountComponent);
  </script>
</body>
</html>

Loading the React library

We've included the source of React as a <script> tag inside the <head> element of our page. It's important to place our <script> loading tags before we start writing our React application otherwise the React and ReactDOM variables won't be defined in time for us to use them.

Also inside head is a script tag that includes a library, babel-core. But what is babel-core?

Babel

Yesterday, we talked about ES5 and ES6. We mentioned that support for ES6 is still spotty. In order to use ES6, it's best if we transpile our ES6 JavaScript into ES5 JavaScript to support more browsers.

Babel is a library for transpiling ES6 to ES5.

Inside body, we have a script body. Inside of script, we define our first React application. Note that the script tag has a type of text/babel:

<script type="text/babel">

This signals to Babel that we would like it to handle the execution of the JavaScript inside this script body, this way we can write our React app using ES6 JavaScript and be assured that Babel will live-transpile its execution in browsers that only support ES5.

Warning in the console?

When using the babel-standalone package, we'll get a warning in the console. This is fine and expected. We'll switch to a precompilation step in a few days.

We've included the <script /> tag here for ease of use.

The React app

Inside the Babel script body, we've defined our first React application. Our application consists of a single element, the <h1>Hello world</h1>. The call to ReactDOM.render() actually places our tiny React application on the page. Without the call to ReactDOM.render(), nothing would render in the DOM. The first argument to ReactDOM.render() is what to render and the second is where:

ReactDOM.render(<what>, <where>)

We've written a React application. Our "app" is a React element which represents an h1 tag. But this isn't very interesting. Rich web applications accept user input, change their shape based on user interaction, and communicate with web servers. Let's begin touching on this power by building our first React component.

Components and more

We mentioned at the beginning of this series that at the heart of all React applications are components. The best way to understand React components is to write them. We'll write our React components as ES6 classes.

Let's look at a component we'll call App. Like all other React components, this ES6 class will extend the React.Component class from the React package:

class App extends React.Component {
  render() {
    return <h1>Hello from our app</h1>
  }
}

All React components require at least a render() function. This render() function is expected to return a virtual DOM representation of the browser DOM element(s).

In our index.html, let's replace our JavaScript from before with our new App component.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello world</title>
  <!-- Script tags including React -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
  <div id="app"></div>
  <script type="text/babel">
    class App extends React.Component {
      render() {
        return <h1>Hello from our app</h1>
      }
    }
  </script>
</body>
</html>

However, nothing is going to render on the screen. Do you remember why?

We haven't told React we want to render anything on the screen or where to render it. We need to use the ReactDOM.render() function again to express to React what we want rendered and where.

Adding the ReactDOM.render() function will render our application on screen:

var mount = document.querySelector('#app');
ReactDOM.render(<App />, mount);

Notice that we can render our React app using the App class as though it is a built-in DOM component type (like the <h1 /> and <div /> tags). Here we're using it as though it's an element with the angle brackets: <App />.

The idea that our React components act just like any other element on our page allows us to build a component tree just as if we were creating a native browser tree.

While we're rendering a React component now, our app still lacks richness or interactivity. Soon, we'll see how to make React components data-driven and dynamic.

But first, in the next installment of this series, we'll explore how we can layer components. Nested components are the foundation of a rich React web application.

Learn React the right way

The up-to-date, in-depth, complete guide to React and friends.

Download the first chapter

Ari Lerner

Hi, I'm Ari. I'm an author of Fullstack React and ng-book and I've been teaching Web Development for a long time. I like to speak at conferences and eat spicy food. I technically got paid while I traveled the country as a professional comedian, but have come to terms with the fact that I am not funny.

Connect with Ari on Twitter at @auser.