« Previous Tutorial Next Tutorial »

Hello again! In our last tutorial, we laid out the directories we’ll need for our React app and built a very simple page template. Today we’re going to get a little fancier as we begin using that template to render various components. We’re going to build a header component and two separate page components, and display one of them via the template. This will be simple, straightforward JSX that is mostly just HTML in render blocks, but we’ll add a few props too just to keep things interesting. In the next tutorial, we’ll introduce React routing, which will allow us to toggle between our two page templates.

This is the fun stuff. At least, I think it is, so let’s get started!

First step, in /src/components, create a subfolder called shared, and inside it, create a new file called Header.jsx. This will be our page header, and it’ll be used on just about every page. It’s going to look a lot like the other React components we’ve been building, for now. Here’s the code:

import React from 'react';

export default function Header(props) {
  const { username } = props;
  return (
    <header>
      <h1>MusicList</h1>
      <div className="user-menu">
        <h2>Welcome { username }</h2>
      </div>
    </header>
  );
}

As you can see, this component takes a username prop and displays it. We’ll be adding more props in future development, but for now that’ll be a handy way to check that our authentication system is working once we build it.

Save that file. Now that our component exists, we need to call it, so open up /src/Template.jsx. It’s convention to add a blank line between functionality imports like line 1, and component imports, so make sure line 2 is blank, and then underneath it add the following:

import Header from './shared/Header';

This snags the export from our component and lets us use it in our JSX, which we’ll do by finding the following three lines:

      <header>
        <h1>MusicList</h1>
      </header>

and replacing them with this one:

      <Header username="anonymous" />

Save the file. If you have your server and hot-reloader up and running, you’ll see the new header pop into place, correctly displaying “anonymous” as the username. Neat!

Now let’s build a page component. Under /src/components, create another subfolder, this one called home and in it create a file called HomePage.jsx where we’ll store the home page of our application.

We’re not going to pass any props to this one, right now, so it’s pretty simple. Here’s the code:

import React from 'react';

export default function HomePage() {
  return (
    <section className="page-content">
      <div className="row">
        <div className="col-sm-12 col-lg-8">
          This is the home page.
        </div>
        <aside className="col-sm-12 col-lg-4">
          This is the sidebar
        </aside>
      </div>
    </section>
  );
}

You’ll probably note a few things here. One of them is that we’re using obvious Bootstrap classes, which means that, yes, we’ll eventually be incorporating Bootstrap into this app. There are lots of opinions on Bootstrap out there … my own is that it’s a super-handy CSS framework that allows a lot of flexibility if you’re a good designer (or work with one). My other opinion is that it’s great for rapid prototyping when you don’t want to spend a ton of time worrying about visuals, which we don’t. If you have a preferred grid system or want to roll your own, well … you do you, but you're on your own!

The other thing you might note is the sidebar. “But wait,” you’re probably saying. “Shouldn’t the sidebar be its own component? And for that matter, shouldn’t we provide for cases in which we don’t want the page to have a sidebar?”

Yes, and yes. The sidebar should be its own component, and we should definitely be able to handle no-sidebar pages. But I’m leaving it like this, for now, to show you why this is a problem that needs to be addressed. Then in a couple of tutorials, we’ll improve the system and fix the issue.

OK, save that page, and then create yet another folder in /src/components. Name this one account and within it create a file called ProfilePage.jsx and fill it with the following code:

import React from 'react';

export default function ProfilePage() {
  return (
    <section className="page-content">
      <div className="row">
        <div className="col-sm-12 col-lg-8">
          This is the profile page.
        </div>
        <aside className="col-sm-12 col-lg-4">
          This is the profile page sidebar
        </aside>
      </div>
    </section>
  );
}

You should have all kinds of complaints about this. Feel free to voice them by shouting at your computer and maybe giving it the middle finger. I can’t hear or see it, so it’s no skin off my back!

For one thing, this code is practically identical to our other page, which seems wasteful and like a good candidate for DRYing our code (DRY stands for Don’t Repeat Yourself and is a fundamental programming concept of great value … which can also be taken too far. We’ll talk about that some other time). For another thing, generally speaking you don’t want to have to rebuild your sidebar every single time you switch pages, because that’s going to lead to inconsistency and annoyance down the road. So, yes, this is bad. But let’s see why it’s bad first, before we fix it.

So, now we have two page components. We can only wire one of them up to our template right now, though (well, we could display both of them at once, but then they wouldn’t exactly be separate pages). Let’s go ahead and add our home page for now. Head back to /src/components/Template.jsx, and just below our import for the Header, add the following line:

import HomePage from './home/HomePage';

And then replace the following three lines:

      <div className="content">
        Content will eventually go here.
      </div>

with this:

      <HomePage />

Save that, watch your hot-reloader hot-reload, and we should be all set. Are you starting to get a feel for how React apps come together? I hope so, because in the next episode, we’re going to start switching between components based on browser URL, using client-side routing. Catch you there!

« Previous Tutorial Next Tutorial »