Ruby on Rails is such a wonderful framework to work with. However, using Embedded Ruby (.erb) and ajax to build apps with dynamic frontends can be painful.
And that's where front-end frameworks like React, Angular, and Ember come in. Since React is the hot thing right now, we're going to use it.
But how do you get React.js set up in a Ruby on Rails application? That's what I'm covering in this article
The first thing you need to do is create your Ruby on Rails application and tell it you're going to use React. To do so type the following code:
rails new react-rails --database=postgresql --webpack=react
I’m also using Postgres as the database in this application.
Now that we have the project set up, we need to add a bit of code so our app knows to use React as the front end.
Let’s go to our routes file at config/routes.rb.
You’re going to do something a little bit different with your routes here. You’re going to wrap all of your calls to your backend in an api namespace.
In this project, we’re going to have a model of Posts. So you’d write your routes like this:
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
root 'pages#index'
namespace :api do
namespace :v1 do
resources :posts
end
end
end
I also added a root route that goes to our pages controller. When making your backend calls to access your controllers, you’re going to have paths such as ‘/api/v1/posts’ to get your posts.
Now we need to tell our app to send other routes to our main React App. We’ll add this to the bottom of our routes file:
get '*path', to: 'pages#index', via: :all
Your file routes file should look like the following:
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
root 'pages#index'
namespace :api do
namespace :v1 do
resources :posts
end
end
get '*path', to: 'pages#index', via: :all
end
Let’s set up our index.jsx file.
Go to app/javascript/packs/hello_react.jsx and rename name that file to index.jsx. Delete most of the stuff there and make the file look like this.
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import App from '../src/components/App'
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<Router>
<Route path="/" component={App}/>
</Router>,
document.body.appendChild(document.createElement('div')),
)
})
If you’ve worked with React before, this should look familiar. We’re importing React, ReactDom, and ReactRouterDom. We’re then importing our main App. Then, we create a node in the DOM and insert our app.
Before we forget, let’s add react-router-dom using Yarn. go to your terminal and type:
yarn add react-router-dom
We’re almost to the point where we can see our app in our front end. Let’s go set up our App.js file.
Create the file “app/javascript/src/components/App.js”. We’re going to get our root path to display our posts. In a “regular rails app” this would be the index page in our posts view folder.
Anyway, here’s what the App.js file should look like:
import React from 'react'
import { Route, Switch } from 'react-router-dom'
import Posts from '../components/Posts/Posts'
const App = () => {
return (
<Switch>
<Route exact path="/" component={Posts} />
</Switch>>
)
}
export default App
Let’s make that Posts page in “app/javascript/src/componenets/Posts/Posts.js”. Here’s what mine looks like.
import React from 'react'
const Posts = () => {
return (
<div>
<h1>Posts</h1>
<p>This is our posts page.</p>
</div>
)
}
export default Posts
Now, we need to tell our view to render our React app. Go to “app/views/layout/application.html.erb” and add the following tag:
<%= javascript_pack_tag 'index' %>
Your layout file should look like the following:
<!DOCTYPE html>
<html>
<head>
<title>ReactRails</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'index' %>
</head>
<body>
<%= yield %>
</body>
</html>
Here, I was about to start my server, but I ran into an “ActiveRecord::ConnectionEstablished” no password supplied error because I did not set up database password in “config.database.yml” so make sure to set up your database settings.
I also had to run rails db:create to create my database
Setting up Postgresql with Rails is out of the scope of this tutorial, sorry!
One more step! We have to set up our PagesController and its view.
Go create a PagesController in “app/controllers/pages_controller”. We just need an index action.
class PagesController < ApplicationController
def index
end
end
And your view file in “app/views/pages/index.html.erb”. My file is a blank file since we’re just loading the layout.
Now run ‘rails s’ and you should see the following:
No alt text provided for this image
Now we have React set up on our Rails app. Congratulations, this is a big step!
Stay tuned for connecting the front end to the back end and adding Redux.
If you want to learn more about web development, make sure to follow me on Twitter.
Top comments (3)
In my opinion, better approach is creating separate applications for front-end and back-end.
I've done that with a MERN app and it just gave me twice the headaches when deploying.
I agree with that. First time it took me more than 10 days to solve issues while deployment.
But separate apps gave you more control and freedom to handle things differently.
e.g. You can use chakraUI or ant-design etc easily on front-end but when you are using single rails app then it is not possible.