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.
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.
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.