Getting up to date on React and Rails
I advertise myself as an expert in JavaScript and Rails when applying for jobs, but there’s a problem.
The last four years I have been really working hard on my own web application toolkit. It’s a passion project.
I love working in my own little world, where everything has a place, and as much as I possibly can I’m working on that ecosystem. So the truth I am NOT up to date on Rails 4, let alone Rails 6.0.
And, this is a little embarrassing to say, but…
I’ve never really made a React app.
There, I said it.
I am a JavaScript developer and I have never typed “react create app” or whatever it is. And would I need to look at documentation to remember how to create a Rails route.
It’s alittle embarrassing when I’m in a job interview for a “Rails Developer” or a “Front End JavaScript Programmer”.
Today that changes.
Setting up Rails 6.0
I honestly didn’t even have my laptop really set up to build Ruby applications:
brew update
(wait 10 minutes)
brew install ruby
(wait 10 minutes)
brew install ruby-build
Welcome to programming.
Apparently for Rails 6.0 I should be using ruby 2.5.3 or 2.6.0:
rbenv install 2.6.0
echo "2.6.0" > ~/.rbenv/version
gem install rails -v 6.0.0.beta1
The computer says “Building native extensions. This could take a while…”
And this is how the cool kids create a Rails app with React:
rails new proxy-me-bro --webpack=react --api -T
Zang. That’s a lot of flags. Let’s break it down:
- We tell Webpack to install React ( — webpack=react)
- API mode means don’t still any of Rail’s HTML views, since React will be handling the HTML ( — api)
- Don’t generate tests (-T) since we don’t even know what we might want to test yet
OK, keeping on…
cd proxy-me-bro
subl .
Alright! I guess that’s a Rails 6 app: Nice!
Get a React component in the browser
Better save our work:
git init
git commit -am "rails + postgres + react"
And now for the React magic:
brew upgrade node
npm install -g create-react-app
create-react-app client
cd client
npm start
Delete some of the junk in the HTML, and…
Nice!
Now, apparently in React everything is a component. My goal for this first demo is to load a simpler version of a few web sites, so I need a text bar I can enter a URL into:
import React, { Component } from 'react'class UrlBar extends Component {
constructor(props) {
super(props);
this.state = {value: "https://www.amazon.com"};this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}handleChange(event) {
this.setState({value: event.target.value});
}handleSubmit(event) {
event.preventDefault();
alert('We should go to ' + this.state.value);
}render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
<input
type="text"
value={this.state.value}
onChange={this.handleChange} />
</label>
<div id="simple-page" />
</form>
);
}
}export default UrlBar
Then we import add a <UrlBar /> in App.js, tweak some styles and we get this:
Pass some simple HTML from the Rails server to the React app
First we need to get the Rails app ready to run:
cd ../
brew install postgresql
brew services start postgresql
bundler add foreman
bundler install
And a Procfile.dev that can start both React and Rails:
web: cd client; PORT=3000 npm start; cd -
api: PORT=3001 bundle exec rails s
And a proxy declaration in our package.json:
"proxy": "http://localhost:3001",
And Rails still uses routes:
# config/routes.rb
Rails.application.routes.draw do
get '/urls/:id',
to: 'application#getUrl',
:constraints => { :id => /.+/ }
end
And controllers:
# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
def getUrl
render :html => "<h1>Simple Amazon</h1><button>Buy Something</button>".html_safe
end
end
NOW, we can run the Rails and React servers together:
foreman start -f Procfile.dev
Finally, install Axios:
npm install axios — save
So we can add a better submit handler inside our UrlBar component…
import axios from 'axios';... handleSubmit(event) {
event.preventDefault();
const url = this.state.value;
axios.get("/urls/"+url)
.then(response => {
document.getElementById("simple-page")
.innerHTML = response.data
})
.catch(error => alert(error))
}
And ZORBS! It works!
Next up
It would probably be instructive to deploy this to the internet, so I’ll try to get this on Heroku next.
And then the next goal is going to be to actually download some real pages in a Rails Active Job queue or whatever, have scripts that build simpler versions of them in React, and then pass them down to the client, maybe with server-side rendering.
Not sure! Just have to take it one step at a time.
Source code
All of this stuff is in up on GitHub if you want to explore!