I was working on understanding how to make React relevant beyond a single page app, and I came across this tutorial by Krithika Muthukumar.
When I got to the end, and I knew what I expected each piece to be doing, nothing happened. None of the components worked at all. I dug in deeper, and saw that some of the required packages were outdated, and after some elimination processes, I found the problem: it used React-Router 3, and the latest version, 4, has changed significantly.
As a challenge to myself, someone who is pretty new to React and with no previous experience with React-Router, I attempted to migrate the tiny, crazy simple app to React-Router 4. And after some brow furrowing and chin scratching, I made it work. This may not be the best way to do things, and there are some things I thought would work but don’t (and I still don’t know why). But it works, and I’m happy about that.
I also made this crazy simple app a tiny bit more complicated by adding a header with links to each of the two pages.
Here’s what I did. (Click here for the Github repo)
Install React Router 4
npm install --save react-router react-router-dom
src/index.jsx
In the index, we’ll have React.DOM
render the App
component, instead of a Router
component. That means we don’t need to import anything from react-router
or ./routes
, and we remove the Router
component.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/app';
require('./stylesheets/base.scss');
require('./stylesheets/home.scss');
require('./stylesheets/contact.scss');
ReactDOM.render(
<App />,
document.getElementById('app')
);
src/components/app.jsx
First, we’ll need to import BrowserRouter
from react-router-dom
, as well as the Routes
component and a new Header
component.
Our App
is going to return
BrowserRouter
so all the child components will have access to the routes. There are a couple of things of note about BrowserRouter
, which replaces Router
. It comes with history included, so we don’t need to worry about managing it. Also, it can only take one child, so we put everything in a <div>
.
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import Header from './views/partials/header';
import Routes from '../routes';
const App = () => (
<BrowserRouter>
<div>
<Header />
<Routes />
</div>
</BrowserRouter>
);
export default App;
src/routes.jsx
Back up to Routes
. This is a bit different than in React Router 3. We’re going to use Switch
, which finds the first matching route and ignores the rest. For the catchall route, we can render()
a function to Redirect
back to ‘/‘.
import React from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import Home from './components//views/home';
import Contact from './components//views/contact';
const Routes = () => (
<Switch>
<Route exact path='/' component={Home} />
<Route path='/contact' component={Contact} />
<Route path='*' render={() => <Redirect to='/' />} />
</Switch>
);
export default Routes;
I created a partials
directory for the Header
component. It needs to import Link
from react-router-dom
to use the routes in Routes
.
import React from 'react';
import { Link } from 'react-router-dom';
const Header = () => (
<div id='Header'>
<span><Link to='/'>Home</Link></span> | <span><Link to='/contact'>Contact</Link></span>
<hr/>
</div>
);
export default Header;
The only significant change here is to remove the componentDidMount()
method, which means we don’t need to import anything from react-router
.
import React from 'react';
const Home = () => (
<div id='home'>
This is the home page.
</div>
);
export default Home;
And
import React from 'react';
const Contact = () => (
<div id='contact'>
This is the contact page.
</div>
);
export default Contact;
And that’s all there is to it. I’m extremely grateful to Krithika Muthukumar for creating the tutorial originally. I have been having a very hard time finding help wrapping my brain around how a multi-page React/Express app would work, and this has helped enormously. I’m also grateful to React Training for the documentation and for making React Router in the first place. Powerful stuff here.