React on Rails Tutorial: Integrating React and Ruby on Rails 5.2
Posted on July 24, 2018 by Daniel Rudnitski
Users expect a certain level of interactivity and speed when using websites, which can be hard to provide with server rendered websites. With a regular Rails project, we can sprinkle interactivity on the client side with vanilla javascript or jQuery but it quickly becomes tedious to maintain and work with for complex user interfaces.
In this tutorial, we’re going to look at integrating React into an existing Rails 5.2 app with the react on rails gem, in order to provide an optimal user experience and keep our codebase clean at the same time.
Suppose you are running your own app store called AppGarage. Users are able to see popular apps, download them, and search for new apps.
Currently, the website is built only with Ruby on Rails so users have to type the whole search term, submit, and wait for a page refresh before seeing the search results.
Users expect content to be loaded as they type so that they can find apps faster. Wouldn’t it be nice to upgrade our search functionality to dynamically fetch and render search results as the user types their query? Let’s do that with React!
TABLE OF CONTENTS
PREREQUISITES
This tutorial assumes a basic understanding of Git, Ruby on Rails, and React/JavaScript.
Ensure the following are installed on your device:
- Ruby on Rails v5.2 or greater
- Git
- Node/NPM/Yarn
INITIAL SETUP
Cloning
We begin by cloning the repository for our project from GitHub which includes the entire static website built with Ruby on Rails and no react integration.
Use the following command to clone the repository:
$ git clone https://github.com/danielrudn/app-garage
After cloning, enter the app-garage
folder:
$ cd app-garage
Migrate and Seed the Database
Now that we pulled down the code for our project, we must prepare rails by migrating and seeding our database:
$ rails db:migrate && rails db:seed
Start Server
Our database now has the correct schema and is seeded with initial sample data in order to easily visualize our code changes. We can now start the rails server (Note: it may take rails a while to start the server on its first run):
$ rails server
You can now head over to http://localhost:3000
and you’ll see that our base application is working. We can view the homepage, search for apps, and view specific apps.
Now that we have a working web app, we’re ready to improve it by integrating React on Rails and modifying the search functionality.
INSTALLING REACT ON RAILS
Note: If you’re following this tutorial using a different existing Rails app or if you’re using a Rails version older than 5.1 you should take a look at the official react-on-rails documentation for integrating with existing rails projects.
Adding and Installing Gems
First, we must add the webpacker
, react_on_rails
and mini_racer
gems. Edit the Gemfile
and add the following to the bottom of the file:
https://gist.github.com/danielrudn/b93db6cb79143e92dc9c2745bae87f61
After adding the gems to the Gemfile
, install them with the following command:
$ bundle install
Setting up Webpacker and React
Now that the required gems are installed, we can begin configuration. First, we configure Webpacker by running:
$ bundle exec rails webpacker:install
Now that webpacker is configured, we install and configure React:
$ bundle exec rails webpacker:install:react
We should now see the following in our terminal:
Webpacker now supports react.js
Note: We can delete the autogenerated sample file: app/javascript/packs/hello_react.jsx
Setting up React on Rails
Currently, our project has Webpacker and supports React but we do not have an integration between React and Ruby on Rails. We need to add our changes to version control, so we add all of our changes and commit with the following command (Note: it’s important to commit our changes otherwise we will get warnings when continuing the tutorial):
$ git add . && git commit -m "Add webpacker & react"
Add the react-dom
and react_on_rails
packages to our package.json
by running:
$ yarn add react-dom react-on-rails
Now create config/initializers/react_on_rails.rb
with the following content:
https://gist.github.com/danielrudn/e27bc67843dadad6db74fe35e54a9cdc
We’re now ready to start writing JavaScript and React components.
IMPLEMENTING THE SEARCH COMPONENT
Starting simple, we’re going to take our current search view and have it render as a React component without changing any functionality.
Create the following structure in your application folder: app/javascript/components
We can now create our search component called Search.jsx
inside the folder we just created with the following content:
https://gist.github.com/danielrudn/d43b7a73d12dce41625d3c48648b5570
The above is our markup for searching converted to JSX in order for React to render it as a component. Note that we changed the HTML class
and autocomplete
attributes to className
and autoComplete
respectively for JSX to properly render our markup. This is required because we are writing JSX which is a syntax extension to JavaScript.
We now have a search component but React on Rails knows nothing about it. Whenever we create a new component that we want to use in our Rails app, we must register it with react-on-rails in order to be able to use it with the react_component
rails helper. To do so, we edit the app/javascript/packs/application.js
file to have the following content:
https://gist.github.com/danielrudn/5c73686e1a0d01d0cbe1686721593860
The application.js
file now serves as a way for us to register our components with react-on-rails. In our case, it’s acceptable to include our search component on every page load, but for real-life production applications, it’s not very performant to include every component on every page. In real-life applications, components would be split into webpack bundles which are loaded on pages where they are needed.
Now we include our application bundle in our layout on every page by editing app/views/layouts/application.html.erb
to have the following content:
https://gist.github.com/danielrudn/fc106217562f824b386a28c0fc91f900
Now, we’ll replace our homepage markup with the react-on-rails react_component
helper to render our Search component by editing app/views/home/index.html.erb
to have the following content:
https://gist.github.com/danielrudn/59c5bba4681d7b94fd3dbfff9f07a2f6
Adding React Functionality to our Replacement
Our search is now rendered as a react component but all of our functionality has remained the same, the only difference is not noticeable to users yet. We’re now able to start making our search dynamic.
We need to be able to fetch our search data as JSON but we currently don’t have a JSON endpoint for our search controller. To do this, we add the file app/views/search/index.json.jbuilder
with the following content:
https://gist.github.com/danielrudn/873b7ab575e9282af2b2fd04749b23a9
Now our search data is accessible as JSON via /search.json
.
To access our search data from the client-side JavaScript, we need to add a library for fetching data asynchronously with the browser. In this tutorial, we’ll use the axios
library since it also supports older browsers. To install the library, simply run the following command in your terminal:
$ yarn add axios
Now that we have our dependencies installed, we can begin improving our search component. We must start tracking the text written into the search field, fetching the search results for the current text, and updating the state. Here is the new content for app/javascript/components/Search.jsx
:
https://gist.github.com/danielrudn/a9b9bbafa491ae58b54aec9c328ea37b
- To start, we defined our components state (and initial state) to include our search results and whether or not we’re currently loading/fetching new results.
- Next, we wrote our
onChange
function which gets called each time the value in the search field changes. We use axios to send an http request to our new/search.json
endpoint with the current search field text. Axios will either successfully fetch results in which case we update our state to include the results, or it will fail and we update our state to have no results. - Our render function stays almost the same. We alter the input field by adding an
onChange
handler and pointing to theonChange
function we just wrote.
The updated search component now dynamically stores and fetches the users search results based on the current text but doesn’t render anything related to the results yet.
Rendering the Dynamic Search Results
In order to render the search components state, we will create two new components that will make our code easier to manage.
First, we create the SearchResult
component which is a purely functional component with no state and it renders declaratively based on props. The prop we expect is a result
which is a regular app
object from our rails application. Create app/javascript/components/SearchResult.jsx
with the following content:
https://gist.github.com/danielrudn/40dc454da34b93a1d3a9f89d614f4a74
Now, we create a SearchResultList
which is also a purely functional component in order to render our result array as SearchResult
components. The SearchResultList
will expect two props, the first is results
, an array of our search results and the second is whether or not we’re currently loading
new results. Create app/javascript/components/SearchResultList.jsx
with the following content:
https://gist.github.com/danielrudn/ed7f1f0fc35df88dc25d66fbd99d39e8
Our SearchResultList
will iterate through our search results and map them to render as a SearchResult
component. We added a style attribute to the container in order to properly display the results under our search field.
Now that we have our two helper components we can modify Search.jsx
to render its state when the result array is not empty. Update app/javascript/components/Search.jsx
with the following content:
https://gist.github.com/danielrudn/8dea4464549f6e008da8a2634dbbe344
The changes we made to the Search
component were:
- Imported our
SearchResultList
component - Updated the
render
function to render theSearchResultList
component when we have results or when we are loading.
We’ve now integrated React on Rails into our Rails 5.2 app in order to have a dynamic search component for our users.
CONCLUSION
We started with a regular rails application and went through the process of installing and configuring Webpacker, React, and React on Rails. After configuring, we replaced our search to be a react component which dynamically fetches and renders search results from a new JSON endpoint on our Rails app.

The original implementation above wasn’t a good user experience since it involved typing the full query, waiting for the page to load before seeing any results.

The new implementation above shows search results as the user types which saves time and provides a much better user experience.
We can now begin adding even more interactivity to our website by implementing additional react components and reusing existing components on other pages.
Preview Final Version
You can preview the final version by following these steps:
- Clone the
final-version
branch of the GitHub Repository$ git clone -b final-version https://github.com/danielrudn/app-garage
- Enter the newly cloned
app-garage
folder:$ cd app-garage
- Run the necessary setup commands:
$ yarn && rails db:migrate && rails db:seed
- Start the rails server and navigate to
http://localhost:3000
Note: Initial load may take a while.$ rails server
Further Reading
If you want to learn more about integrating react with Ruby on Rails (such as proper state management with Redux or handling bundles for specific pages), the repository and documentation for react on rails is a great place to look.
Tags: javascript, jsx, rails, react on rails, ruby, ruby on rails, spa