CONNERJENSEN

Learn Rails, JavaScript and Software Architecture.

A Rails & React Tutorial

A Rails & React Tutorial

April 03, 2021

Time To Read: 7 Minutes

Author: Conner Jensen

What we're going to do

In this article we are going to walk through how to use React in a Ruby on Rails project. Ruby on Rails is still an excellent choice for your backend and in this article you will see why.

Rails allows for extremely fast development, and coupled with a React frontend, you can create robust and interactive web apps at lightning speed!

In this guide I'm assuming you are using a recent version of Ruby and Rails version 6.*.*

If you don't have these installed then you can get started by going here for Ruby and here for Rails.

We will first create an initial rails application, then add the necessary gems to get react to work with rails.

At the end of this tutorial, you should have a Rails application set up to work with React. You will be able to create reusable React components and mix and match erb with react as needed.

Let's get started!

Go ahead and run the following command to generate a new Rails project.

rails new rails_with_react

This is somewhat like create-react-app if you are coming from the React world.

change directories into your new Rails project

cd rails_with_react

We will now install the gems required to use React with Rails.

Add the gem 'react-rails' to your Gemfile

gem 'react-rails'

Gemfiles are like package.json files, they keep track of your dependencies.

Run bundle install to fetch this gem from rubygems.org

bundle install

Then run the install commands for the gem

rails generate react:install
rails webpacker:install:react

These commands set up a app/javascript/component/ directory and add a few lines to your app/javascript/packs/application.js file.

Now that you have the react-rails gem installed, it's time to put it to work.

Let's run the following command to generate our first React component.

rails g react:component FirstComponent

Go to your app/javascript/components/ directory and you will see a new file called FirstComponent.js Nice work!

If you've had any problems up until this point you should check that you are using the correct version of rails and ruby. Please leave a comment below if you are having any issues with this tutorial.

We now have our first component built (which is great!), but we still need to put it in one of our views so our users can see it.

Let's run the rails scaffolding command so we have a place to render our React component

rails g scaffold random_name

Go to your newly generated views/random_name/index.html.erb template.

Erb templates are Rails way of doing dynamic frontend content, however, we are just going to use it to render a React app.

Let's put the following line in the index template.

# /views/random_name/index.html.erb
<%= react_component("FirstComponent") %>

Migrate your database

rails db:migrate

And now you can start up your app!

rails s

Open up your browser and go to localhost:3000/random_name in order to render the random_name/index.html.erb template.

At this point your component will be rendering to the page, however, your component doesn't have any content to display, let's go add some.

Open up app/javascript/components/FirstComponent.js

It should look like this

// app/javascript/components/FirstComponent.js
import React from 'react'
import PropTypes from 'prop-types'
class FirstComponent extends React.Component {
  render() {
    return (
      <React.Fragment>
      </React.Fragment>
    );
  }
}

export default FirstComponent

Let's go ahead and add some text in this component so we can see it on the screen.

// app/javascript/components/FirstComponent.js
import React from 'react'
import PropTypes from 'prop-types'
class FirstComponent extends React.Component {
  render() {
    return (
      <React.Fragment>
       Hello From The React Component!       </React.Fragment>
    );
  }
}

export default FirstComponent

You should see the text "Hello From The React Component!" displayed on your screen.

Rails & React Tutorial

If you don't, then something went wrong in one of the above steps, you can ask for help down below or go back and retry some of them to see if they work the second time.

Let's add a little bit of extra functionality to our React component.

First we will add an input box.

// app/javascript/components/FirstComponent.js
import React from 'react'
import PropTypes from 'prop-types'
class FirstComponent extends React.Component {
  render() {
    return (
      <React.Fragment>
       Hello From The React Component!
       <input type="text">      </React.Fragment>
    );
  }
}

export default FirstComponent

Then add a function that we will call when our input box changes and an initial state for our component.

// app/javascript/components/FirstComponent.js
import React from 'react'
import PropTypes from 'prop-types'
class FirstComponent extends React.Component {
  constructor() {
    state = {userInput: ""}    this.onUserInput = this.onUserInput.bind(this)  }

  onUserInput(e) {    this.setState({      userInput: e.target.value    })  }
  render() {
    return (
      <div>
       Hello From The React Component!
       <input type="text" onChange={(e) => this.onUserInput(e)} />       <span>{this.state.userInput}</span>      </div>
    );
  }
}

export default FirstComponent

You should now see the following and be able to type into your input box and see the result!

Rails & React Tutorial

At this point we have a fully functioning React component, which we can extend into a robust React application. However, React has switched to a functional style of component that is more commonly used these days.

Let's do a quick refactoring of our component to use this new functional style!

I'll show the finished refactoring first, then we will walk through each part of it together.

// app/javascript/components/FirstComponent.js
import React, {useState} from "react"
import PropTypes from "prop-types"
export default function FirstComponent() {
  const [userInput, setUserInput] = useState("");

  return (
    <div>
      Hello From The React Component!
      <input type="text" onChange={(e) => setUserInput(e.target.value)} />
      <span>{userInput}</span>
    </div>
    )
 }

Just by looking at the refactoring using the new functional style, you can see why the React community has switched over. I think it is much more readable and less code overall.

Let's go line by line of the new refactoring and explain what's going on.

As you can see we still import React, however we no longer import Component, instead we are importing what is know as a "hook" called useState.

We store our state in the useState hook instead of in the constructor by using this.state like we did before.

// app/javascript/components/FirstComponent.js
import React, {useState} from "react"import PropTypes from "prop-types"
export default function FirstComponent() {
  const [userInput, setUserInput] = useState("");

  return (
    <div>
      Hello From The React Component!
      <input type="text" onChange={(e) => setUserInput(e.target.value)} />
      <span>{userInput}</span>
    </div>
    )
 }

The next thing you will notice is we are no longer using a class we are using a plain old javascript function.

Because of this we can also get rid of the constructor method and the render method.

// app/javascript/components/FirstComponent.js
import React, {useState} from "react"
import PropTypes from "prop-types"
export default function FirstComponent() {  const [userInput, setUserInput] = useState("");

  return (
    <div>
      Hello From The React Component!
      <input type="text" onChange={(e) => setUserInput(e.target.value)} />
      <span>{userInput}</span>
    </div>
    )
 }

Here you can see we are using the useState hook, that we imported above, in order to set an initial state of an empty string "" and to give us a setter function setUserInput that we can use to update the state.

// app/javascript/components/FirstComponent.js
import React, {useState} from "react"
import PropTypes from "prop-types"
export default function FirstComponent() {
  const [userInput, setUserInput] = useState("");
  return (
    <div>
      Hello From The React Component!
      <input type="text" onChange={(e) => setUserInput(e.target.value)} />
      <span>{userInput}</span>
    </div>
    )
 }

Finally, we use our new setUserInput function in order to update the state whenever the user types into our input box.

// app/javascript/components/FirstComponent.js
import React, {useState} from "react"
import PropTypes from "prop-types"
export default function FirstComponent() {
  const [userInput, setUserInput] = useState("");

  return (
    <div>
      Hello From The React Component!
      <input type="text" onChange={(e) => setUserInput(e.target.value)} />      <span>{userInput}</span>
    </div>
    )
 }

At this point your app should be working the exact same as it was before we did our refactoring. It is recommended that you use this new functional style when creating new React components.

Thank you very much for taking the time to go through this Rails & React tutorial, I hope you learned something new!

If you had any trouble during this tutorial feel free to reach out to me and I'll do my best to help you debug.

If you're interested in more Ruby and Rails content you can check out this post I wrote about The Ruby Programming Language

Join My Email List

Get post notifications and tips delivered to your inbox

By subscribing, you acknowledge to have read & agreed to our Privacy Policy.