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:
Top comments (4)
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)
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
andPOST
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 thepost
ornew_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!
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!
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...