Reactify a non-reactive express app

Last Friday, with two other students from General Assembly, we completed our first project. However, this week we dove into React.js and immediately I wanted to redo the front-end to make our app truly single-page.

Specifically, I wanted to accomplish the following:

  1. Use create-react-app to make a separate front-end app
  2. Host it separately from the back end to get around Heroku’s restrictions on ports. This requires setting up CORS — see below
  3. Separate our monolithic index.html into React components
  4. Rip out all JQuery and replace with axios/react.
  5. Implement routes to redirect between the landing and content pages.
  6. Reconnect events to React components.

1. create-react-app

Is pure magic.

2. CORS

In the course of this process I quickly discovered that hosting the front and back separately (even on localhost with different ports) is called CORS: “Cross Origin Resource Sharing” and that this is disabled by default! “Cross Origin” means that the two servers are not hosted on the same domain and port. Here is how to set up middleware that sets the correct headers to enable CORS in Express.js:

app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,
contentType, Content-Type, Accept, Authorization");
next();
});

This is tedious, considering that our back end will only ever receive requests from a host that is not our own. I imagine this makes sense for authentication purposes, but we don’t have that set up for our app. Turns out, there is a CORS NPM package that sums up the above code:

const cors = require('cors');
app.use(cors());

Much cleaner.

3. Separate HTML into Components

I won’t paste my whole index.html into this post, but basically I wrapped pieces of the HTML inside the following boilerplate:

import React, { Component } from 'react';
class Child extends Component {
render() {
return(
<your-html-here>
);
}
}
export default Child;

And then imported them appropriately into their parent components:

import React, { Component } from 'react';
import Child from './Child';
class Parent extends Component {
render() {
return(
<Child />
);
}
}
export default Parent;

This process took very little time and in the end, my output more or less matched the previous statically served (and javascript DOM manipulated) pages. But I broke all my javascript of course.

4. axios/react

The main function of my event listeners was to call my back end API. Previously this was done with AJAX via jQuery, but I’m not a huge fan of jQuery. Axios, however, can turn this:

$.ajax({
method: 'POST',
url: `/playlists`,
dataType: 'json',
data: {
name: newName,
description: newDescr
},
success: redirectFunction,
error: (err) => { console.log(err); }
});

Into this:

axios.post('/playlists', {
name: newName,
description: newDescr
})
.then(redirectFunction)
.catch(err => {
console.log(err);
})

We lose jQuery bloat and gain code clarity.

Stay tuned for the follow up post on hooking up events and using them to trigger redirects and UI updates!