Build out the site with React Components

In this article we're going to build out the blog front page in React in preparation for the rest of the production optimizations we're going to do, including server-side rendering. Alot of what I talk about will be applicable to other frontend-frameworks. Since they all follow the same ES6 style modular design. If there's a need, I'll cover any differences you'll come across, in the choose your own adventure section.

We're going to start with a special branch that includes the HMR changes from the "Hooking Up React" lesson and all the work we've done on making our code work in production.

You should check this branch out.

git clone https://github.com/lawwantsin/webpack-course.git
cd webpack-course
git checkout react-components
npm install

We're going to kick things off by moving the content in index.ejs to an app root component.

We'll cut the profile out of the index.ejs and replace it with a single element.

<html>
  <head>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="react-root"></div>
  </body>
</html>

Inside counter.js, let's switch this component that we built in "Hooking up React", with the guts of the profile.

import React from "react"

export default class extends React.Component {
  constructor(props) {
    super(props)
    this.state = {}
  }

  render() {
    return ( // Pasted
      <div class="profile">
        <img src= <%= require("../images/link.jpg") %> />
        <h1>Links Journal</h1>
        <div class="content">
          Lorem ipsum...
        </div>
      </div>
    )
  }
}

Now, of course, this will error out, as the syntax is for EJS, not JSX.

EJS Syntax error in React

But we can fix that pretty quickly. Let's first change all of the class attributes to className. Then, let's change all <%= %> to {}. So that render function should look like this:

render() {
  return (
    <div className="profile">
      <img src={require("../images/link.jpg")} />
      <h1>Links Journal</h1>
      <div className="content">
        Lorem ipsum...
      </div>
    </div>
  )
}

Okay, that looks better.

EJS Syntax error in React

Now in src/app.js, you notice, there's a reference to the counter.js file. This isn't a counter anymore. It's kinda like the root of the app now. So let's change the name of this file.

mkdir src/components
mv src/counter.js src/components/AppRoot.js

And change that reference in app.js to AppRoot.

import React from "react"
import ReactDOM from "react-dom"
import AppRoot from "./components/AppRoot"
import { AppContainer } from "react-hot-loader"

function render(Component) {
  ReactDOM.render(
    <AppContainer>
      <Component />
    </AppContainer>,
    document.getElementById("react-root")
  )
}
render(AppRoot)

if (module.hot) {
  module.hot.accept("./components/AppRoot.js", () => {
    const NewAppRoot = require("./components/AppRoot.js").default
    render(NewAppRoot)
  })
}

Data in React Components

Okay, what are we making anyway? This isn't really a profile. It's, well, I guess it's an About me page. So let's update that to say something real and pull that into react through a variable.

We're going to create some data in a file and import the data into react, so we're not polluting our components with a lot of text.

mkdir data
touch data/bio.js

Inside the bio.js file write something, anything or copy what I wrote:

module.exports = "Hello Everybody, welcome to my journal."

In the AppRoot.js, let's import the data and use it directly in our component.

At the top:

import BioText from "../../data/bio"

In the render method:

<div className="content">{BioText}</div>

Cool. Now we have a sense of separating component from data. We'll improve this in future articles with markdown and fetching from the server, as this bio.js will be bundled with the main-bundle.js

In Sum

Okay. Now we've got a real path moving forward into the React/Webpack ecosystem. The HMR works nicely in development and we haven't changed production much. We'll address server-side rendering soon enough as we round out this section.

Up Next

Our CSS is out of control. Well, not really, but we should clean that up too. In the next article, we'll be introducing my favorite kind of CSS tech so far.