Intro to React Router
In the example to the right, we demonstrate a simple example using React Router v6. We start with this example and by walking through React Router components as this is the scaffolding that is required for us to render different pages (React components) in our app based on the current URL path.
BrowserRouter
The BrowserRouter is a type of Router component given to us by React Router. This component provides location context for our app. It must be the top level component so that each child component we render from React Router can access the same context.
Routes
The Routes component is a container for a nested tree of <Route>
elements that renders the first branch (the Route and any nested child routes) that best matches the current location. We should render this directly beneath the BrowserRouter component.
Route
The Route component declares an element that should be rendered at a certain URL path. We will discuss some of the available props for the Route component below. You can review the docs for the Route component here.
Nested Routes in React Router
You will first notice that we are nesting Route components within a Route component. Let's discuss why.
For our app, we always want to render a specific component on the page - Layout. This component will render a NavBar that we always want the user to see regardless of what URL or page they are viewing. In order to accomplish this, child routes are used in combination with an Outlet
component.
Child routes paths can match relatively to the parent route. So in our example, we're actually rendering a layout route for the parent component, which will default to the /
path.
Layout routes
In React Router, if we omit the path, we are technically rendering a layout route. From the docs, a layout route is a "A parent route without a path, used exclusively for grouping child routes inside a specific layout." So, we omit the path, this component will default to the /
path, which will ensure we match relatively to the child routes, essentially rendering on all paths. This is a bit misleading and it may be less confusing to not mention this concept and just use a path="/"
to be more explicit.
Outlet component
React Router's Outlet component tells React Router to render any matching child route components there. So, since we have rendered Layout at the top level with the default /
path, any matching child routes will be determined relatively to this path, so for example /missions
will render both the parent /
route and the child route path component missions
. The Missions
component will be rendered where the Outlet
component is, in this case beneath the NavBar
component inside the Layout
component.
Index route
So, since missions
path renders the Missions component, how does the Home path render? This is through the index
prop of the Route. This tells our Router to render this Route if it exactly matches the parent's route. So, a route of /
(the route URL of the page), will render both the Layout, and then render the Home
component inside the Layout's Outlet
.
Why is this a solid React Router pattern?
This pattern allows us to easily render new pages in our app without having to duplicate the Navbar component in each page. Additionally, we can style the Layout to keep a consistent layout style for each of our pages.
import { BrowserRouter, Routes, Route, Outlet, Link } from "react-router-dom"; function NavBar() { return ( <div style={{ margin: "10px 0px" }}> <Link to="/"> Home </Link> <Link to="/missions"> Missions </Link> <Link to="/logs"> Logs </Link> </div> ); } function Layout() { return ( <div> <NavBar /> <Outlet /> </div> ); } function Home() { return <div> Home </div>; } function Missions() { return <div> Missions </div>; } function Logs() { return <div> Logs </div>; } function App() { return ( <BrowserRouter> <Routes> <Route element={<Layout />}> <Route index element={<Home />} /> <Route path="missions" element={<Missions />} /> <Route path="logs" element={<Logs />} /> </Route> </Routes> </BrowserRouter> ); } export default App;