The App component in the preceding example was the main component of the application. This is because it defined the root URL: /. However, once the user navigated to a specific feature URL, the App component was no longer relevant.
In versions of react-router prior to version 4, you could nest your <Route> elements so that as the path continues to match the current URL, the relevant component is rendered. For example, the path /users/8462 would have nested <Route> elements. In version 4 and above, react-router no longer uses nested routes for handling child content. Instead, you have your App component as you normally would. Then, <Route> elements are used to then match paths against the current URL in order to render specific content in App.
Let's take a look at a parent App component that uses <Route> elements to render child components:
import React from 'react';
import {
BrowserRouter as Router,
Route,
NavLink
} from 'react-router-dom';
// The "User" components rendered with the "/users"
// route.
import UsersHeader from './users/UsersHeader';
import UsersMain from './users/UsersMain';
// The "Groups" components rendered with the "/groups"
// route.
import GroupsHeader from './groups/GroupsHeader';
import GroupsMain from './groups/GroupsMain';
// The "header" and "main" properties are the rendered
// components specified in the route. They're placed
// in the JSX of this component - "App".
const App = () => (
<Router>
<section>
<nav>
<NavLink
exact
to="/"
style={{ padding: '0 10px' }}
activeStyle={{ fontWeight: 'bold' }}
>
Home
</NavLink>
<NavLink
exact
to="/users"
style={{ padding: '0 10px' }}
activeStyle={{ fontWeight: 'bold' }}
>
Users
</NavLink>
<NavLink
exact
to="/groups"
style={{ padding: '0 10px' }}
activeStyle={{ fontWeight: 'bold' }}
>
Groups
</NavLink>
</nav>
<header>
<Route exact path="/" render={() => <h1>Home</h1>} />
<Route exact path="/users" component={UsersHeader} />
<Route exact path="/groups" component={GroupsHeader} />
</header>
<main>
<Route exact path="/users" component={UsersMain} />
<Route exact path="/groups" component={GroupsMain} />
</main>
</section>
</Router>
);
export default App;
First, the App component renders some navigation links. These will always be visible. Since these links point to pages in your app, you can use the NavLink component instead of the Link component. The only difference is that you can use the activeStyle property to change the look of the link when its URL matches the current URL.
Next, you have the header and main sections. This is where you use the Route component to determine what is rendered in this part of the App component. For example, the first route in <header> uses the render property to render the title when the user is at the root of the app. The next two Route components use the component property to render other header content. The same pattern is used in <main>.
Nested routes can get messy fast. With this flat structure of declaring routes, it's easier to scan the routes in your code to figure out what's happening.
This application has two features—users and groups. Each of them has its own App components defined. For example, UsersHeader is used in <header> and UsersMain is used in <main>.
Here's what the UsersHeader component looks like:
import React from 'react';
export default () => <h1>Users Header</h1>;
And here's what the UsersMain component looks like:
import React from 'react';
export default () => <p>Users content...</p>;
The components used in the groups feature look almost exactly the same as these. If you run this example and navigate to /users, here's what you can expect to see:
