DEV Community

Cover image for Rails with React - One Repo - Part 2
Harry Levine
Harry Levine

Posted on

Rails with React - One Repo - Part 2

Part 2 of 3: Integrating React Router

Recap

In part 1 of this series we covered setting react as the view layer.

All of the code for this series resides at: https://github.com/oddballio/rails-with-react

Introduction

As we now have the view layer staged, next we will want to be able to visit many different pages in our application, each with their own purpose. For example:

  • a home page
  • a page that displays a list of posts
  • a page with a form to create a new post

In order to create multiple React components with multiple, unique URLs, we will integrate React Router.

Create and import new components

Let's create a class component to represent each of these pages, with some boilerplate content.

1. Create app/javascript/components/Home.js

// app/javascript/components/Home.js

import React from 'react'

class Home extends React.Component {
  render() {
    return (
      <div>
        Home page
      </div>
    )
  }
}

export default Home

2. Create app/javascript/components/Posts.js

// app/javascript/components/Posts.js

import React from 'react'

class Posts extends React.Component {
  render() {
    return (
      <div>
        Posts page
      </div>
    )
  }
}

export default Posts

3. Create app/javascript/components/NewPost.js

// app/javascript/components/NewPost.js

import React from 'react'

class NewPost extends React.Component {
  render() {
    return (
      <div>
        NewPost page
      </div>
    )
  }
}

export default NewPost

4. Import the components into App.js

// app/javascript/components/App.js

import React from 'react'
import Home from './Home'
import Posts from './Posts'
import NewPost from './NewPost'

...

Install and import dependencies

1. Install React Router and react-router-dom

$ yarn add react-router
$ yarn add react-router-dom

2. In index.js import the relevant package components

// app/javascript/packs/index.js

...
import { BrowserRouter as Router, Route } from 'react-router-dom'

Setup the Router and Routes

Let's integrate the components from these new packages.

1. In index.js, instead of passing in the App component, we'll pass in the package's Router component

// app/javascript/packs/index.js

...
document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <Router>

    </Router>,
    document.body.appendChild(document.createElement('div')),
  )
})

2. Within the Router component, we'll add a Route component that establishes a root path, with App.js as our root component

// app/javascript/packs/index.js

...
    <Router>
      <Route path="/" component={App} />
    </Router>,

Create the routes in the React app

As App.js is set as the root component for the router, it will contain all of the individual routes for each component.

1. In App.js, import the Route and Switch components from react-router-dom

// app/javascript/components/App.js

...
import { Route, Switch } from 'react-router-dom'

2. In App.js, establish all of the unique routes within a Switch component

// app/javascript/components/App.js

...
class App extends React.Component {
  render() {
    return (
      <div>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route exact path="/posts" component={Posts} />
          <Route exact path="/new_post" component={NewPost} />
        </Switch>
      </div>
    )
  }
}

export default App

Umbrella Rails route for all React routes

We need to create a catchall route that matches any of the potential routes that might come from our React app, and funnel them to our pages_controller#index action. This being the action that renders our React application.

Important: This match route must be the last route in routes.rb to ensure that it does not mistakenly absorb any other routes.

1. In routes.rb create the catchall route

# config/routes.rb

Rails.application.routes.draw do
  root 'pages#index'

  # IMPORTANT #
  # This `match` must be the *last* route in routes.rb
  match '*path', to: 'pages#index', via: :all
end

2. Start the rails server with rails s
3. In a separate tab run the bin/webpack-dev-server script

$ bin/webpack-dev-server

This sets up the real time reloading that is standard with a basic React app.

4. Visit http://localhost:3000/

You should see "Home page"

5. Visit http://localhost:3000/posts

You should see "Posts page"

6. Visit http://localhost:3000/new_post

You should see "NewPost page"

Next Steps

There is one more tutorial in this series:

Part 3 of 3: Handling Requests Between React and Rails

Top comments (4)

Collapse
 
cirogolden profile image
Ciro Golden

what happens if you just see a blank page? instead... the webpack-dev-server complied fine and the server started but im not seeing anything just a blank page.

Processing by PagesController#index as HTML
Rendering pages/index.html.erb within layouts/application
Rendered pages/index.html.erb within layouts/application (3.6ms)
Completed 200 OK in 1134ms (Views: 1132.3ms | ActiveRecord: 0.0ms)

Collapse
 
harrymlevine profile image
Harry Levine • Edited

It is hard to say without seeing the error(s) and/or your code. For Ruby/Rails errors, you'll follow the server logs, which are in the tab you are running the rails s command.

Whenever you're working with React, or any JavaScript library, be sure to have the Chrome dev tools console open. That is where any JavaScript errors might be surfaced. Another place to look for JavaScript errors could be the tab you are running bin/webpack-dev-server in.

For monitoring the GET and POST calls being made when you visit the different routes, be sure to have the Chrome dev tools network tab open, and check for any non-200 statuses for the post or new_post calls.

Perhaps try comparing your code to the sample app:

github.com/oddballio/rails-with-react

You'll want to compare all of the files that have been touched as part of this tutorial, as well as the Gemfile and package.json files.

Hope that helps!

Collapse
 
cirogolden profile image
Ciro Golden

I got it to work!!! my Ruby wasn't the version it was on this tutorial and i was able to make everything work this time around! i'm very happy and excited to go to the next step finally!!
Thank you!

Collapse
 
cirogolden profile image
Ciro Golden

copied every step but I couldn't figure out why... tried to install different npm dependencies from peoples suggestions from stack overflow.. and ended up just ruining everything... 4 hours of work to have to start again...