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!

Complex Components

Edit this page on Github

Awesome, we've built our first component. Now let's get a bit fancier and start building a more complex interface.

In the previous section of 30 Days of React, we started building our first React component. In this section, we'll continue our work with our App component and start building a more complex UI.

A common web element we might see is a user timeline. For instance, we might have an application that shows a history of events happening such as applications like Facebook and Twitter.

We could build this entire UI in a single component. However, building an entire application in a single component is not a great idea as it can grow huge, complex, and difficult to test.


// Don't do it like this. This is for example only
class Panel extends React.Component {
  render() {
    return (
      <div className="notificationsFrame">
        <div className="panel">
          <div className="header">
            
            <div className="menuIcon">
              <div className="dashTop"></div>
              <div className="dashBottom"></div>
              <div className="circle"></div>
            </div>

            <span className="title">Timeline</span>

            <input
              type="text"
              className="searchInput"
              placeholder="Search ..." />

            <div className="fa fa-search searchIcon"></div>
          </div>
          <div className="content">
            <div className="line"></div>
            <div className="item">

              <div className="avatar">
                <img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
                Doug
              </div>

              <span className="time">
                An hour ago
              </span>
              <p>Ate lunch</p>
            </div>

            <div className="item">
              <div className="avatar">
                <img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
              </div>

              <span className="time">10 am</span>
              <p>Read Day two article</p>
            </div>

            <div className="item">
              <div className="avatar">
                <img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
              </div>

              <span className="time">10 am</span>
              <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
            </div>

            <div className="item">
              <div className="avatar">
                <img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
              </div>

              <span className="time">2:21 pm</span>
              <p>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</p>
            </div>

          </div>
        </div>
      </div>
    )
  }
}

Breaking it down

Rather than build this in a single component, let's break it down into multiple components.

Looking at this component, there are 2 separate parts to the larger component as a whole:

  1. The title bar
  2. The content

We can chop up the content part of the component into individual places of concern. There are 3 different item components inside the content part.

If we wanted to go one step further, we could even break down the title bar into 3 component parts, the menu button, the title, and the search icon. We could dive even further into each one of those if we needed to.

Deciding how deep to split your components is more of an art than a science.

In any case, it's usually a good idea to start looking at applications using the idea of components. By breaking our app down into components it becomes easier to test and easier to keep track of what functionality goes where.

The container component

To build our notifications app, let's start by building the container to hold the entire app. Our container is simply going to be a "wrapper" for the other two components.

None of these components will require special functionality (yet), so they will look similar to our HelloWorld component in that it's just a component with a single render function.

Let's build a wrapper component we'll call App that might look similar to this:


class App extends React.Component {
  render() {
    return (
      <div className="notificationsFrame">
        <div className="panel">
          {/* content goes here */}
        </div>
      </div>
    )
  }
}

Notice that we use the attribute called className in React instead of the HTML version of class. Remember that we're not writing to the DOM directly and thus not writing HTML, but JSX (which is just JavaScript).

The reason we use className is because class is a reserved word in JavaScript.

Child components

When a component is nested inside another component, it's called a child component. A component can have multiple children components. The component that uses a child component is then called it's parent component.

With the wrapper component defined, we can build our title and content components by, essentially, grabbing the source from our original design and putting the source file into each component.

For instance, the header component looks like this, with a container element <div className="header">, the menu icon, a title, and the search bar:


class Header extends React.Component {
  render() {
    return (
      <div className="header">
        <div className="fa fa-more"></div>

        <span className="title">Timeline</span>

        <input
          type="text"
          className="searchInput"
          placeholder="Search ..." />

        <div className="fa fa-search searchIcon"></div>
      </div>
    )
  }
}

And finally, we can write the Content component with timeline items. Each timeline item is wrapped in a single component, has an avatar associated with it, a timestamp, and some text.


class Content extends React.Component {
  render() {
    return (
      <div className="content">
        <div className="line"></div>

      {/* Timeline item */}
        <div className="item">
          <div className="avatar">
            <img src="http://www.croop.cl/UI/twitter/images/doug.jpg" />
            Doug
          </div>

          <span className="time">
            An hour ago
          </span>
          <p>Ate lunch</p>
          <div className="commentCount">
            2
          </div>
        </div>

        {/* ... */}

      </div>
    )
  }
}

In order to write a comment in a React component, we have to place it in the brackets as a multi-line comment in JavaScript.

Putting it all together

Now that we have our two children components, we can set the Header and the Content components to be children of the App component. Our App component can then use these components as if they are HTML elements built-in to the browser. Our new App component, with a header and content now looks like:


class App extends React.Component {
  render() {
    return (
      <div className="notificationsFrame">
        <div className="panel">
          <Header />
          <Content />
        </div>
      </div>
    )
  }
}

With this knowledge, we now have the ability to write multiple components and we can start to build more complex applications.

However, you may notice that this app does not have any user interaction nor custom data. In fact, as it stands right now our React application isn't that much easier to build than straight, no-frills HTML.

In the next section, we'll look how to make our component more dynamic and become data-driven with React.


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.