React is great for implementing small widgets and parts of any existing web application, but this framework really shows its strength when you build an entire application with it. But in order to do that, you probably need a few different routes.
Although there are many frameworks for implementing routing in React (or to create your own), most people end up using the amazing React Router from React Training. React Router has a declarative approach to defining routes, which means that everything is pretty much regular components.
So let's get started!
The first thing you need to do is to mount a <BrowserRouter />
component. This component wraps your entire
application and uses the HTML5 History API to keep the URL and your application's UI in sync.
import { BrowserRouter } from 'react-router-dom';
import App from './App';
const Root = () => (
<BrowserRouter>
<App />
</BrowserRouter>
);
The BrowserRouter
component accepts a basename
property which lets you set the base path for your
application. If you're writing an app that runs at some sub-path of a website (like /path/to/your/app), then you can specify this here. You won't need to re-write that part of the URL in every link throughout the app.
Specify your routes!
Since react-router
's routes are regular components, you can render them wherever you want. As long as you keep them
inside the <BrowserRouter />
component, any <Route />
will render whenever it matches the current route.
However, you typically want some top level routes to handle your application flow. This is the typical setup I use in my own applications:
import { Route } from 'react-router-dom';
const App = () => (
<div>
<SiteHeader />
<main>
<Route path="/" exact component={FrontPage} />
<Route path="/about" component={AboutPage} />
</main>
<SiteFooter />
</div>
);
Each <Route />
component requires a path
property (which specifies a route to match), an exact
flag to
specify whether you want the route to match any path that matches or only the exact string, and a component
prop
that specifies what to render whenever the route matches. Easy as pie, right?
Some bonus components
I'm not going to write an entire tutorial on react-router
- there are way too many good ones out there (check the
resources below!), but here's a few components that's good to know:
<Link />
This component is used to link internally in your app. It works just like an <a />
tag, but instead of href
you
write to
:
<Link to="/about">About me</Link>
<Redirect />
If you want to redirect your user (like if you click on a link that is not yet available, like tomorrow's article), you
can render a <Redirect />
component instead of your regular component.
const Article = props => {
if (!props.isAvailable) {
return <Redirect to="/" />;
}
return <Article title={props.title} body={props.body} />;
};
withRouter
When you render a route, the component usually gets three props provided - history
, match
and location
.
These are useful when you need to fetch stuff from a parameterized URL, manipulate history or just fetch the current
location parameters.
If you need these somewhere further down your render tree, however, you might want a shortcut instead of passing these down from the top level component.
withRouter
is a higher order component that provides these three props to whatever component that needs them:
import { withRouter } from 'react-router-dom';
const SomeComponent = props => (
<div>
<p>The current URL is {props.location.pathname}.</p>
<button onClick={() => props.history.goBack()}>
Go back to the last page
</button>
</div>
);
const SomeComponentWithRouterProps = withRouter(SomeComponent);
Learn once, write anywhere!
One of the main selling points of React is that you can use the same techniques to write code wherever - on the web,
on the server or even in native mobile apps. This is why you see me importing react-router-dom
everywhere - there
is a matching library for React Native, and you can use the <StaticRouter />
component instead of
<BrowserRouter />
whenever you need to render your app on the server.
Hope you learned something, and that you'll use this on your next project!