React router nav bar example
For @Chris 's answer to work in a functional component. Here is the answer React-router, router-dom versions v5.2.0
import React from 'react';
import { Link, Switch, Route } from 'react-router-dom';
import Header from './header';
import Footer from '.footer';
import Page1 from './page1';
import Page2 from './page2';
import Page3 from './page3';
import Loading from './Loading'; // a page to show spinner
const Dashboard = React.lazy(() => import('../pages/Dashboard'));
// if you have an admin dashboard to load lazily
const NavRoute = ({exact, path, component: Component}) => (
<Route exact={exact} path={path} render={(props) => (
<div>
<Header/>
<Component {...props}/>
<Footer/>
</div>
)}/>
)
function App() {
return (
<div>
<Suspense fallback={<Loading />}>
<Switch>
<NavRoute exact path="/" component={Landing} />
<Route exact path="/admin/dashboard" component={Dashboard}/>
<Route exact path="/" component={Login} />
<NavRoute exact path="/path1" component={Page1} />
<NavRoute exact path="/path2" component={Page2} />
<NavRoute component={Page404} />
</Switch>
</Suspense>
</div>
);
}
export default App;
React router version 6+ 2021 Routes With/Without Navbars
import { Outlet, Route, Routes } from "react-router-dom";
// your components here
const App = () => {
return (
<>
<Routes>
{/* Routes that needs a navbar will need to go as children of this Route component */}
<Route path="/" element={<LayoutsWithNavbar />}>
<Route path="/" element={<div>Home screen</div>} />
<Route path="/welcome" element={<Welcome />} />
<Route path="/something" element={<Somethinggg />} />
<Route path="/somethingProtected" element={<YourCustomProtectedRoute component={Someone}/>} />
<Route path="/something/:id" element={<ProtectedRoute id component={SomethingById}/>} />
</Route>
{/* Routes without a navbar you can add them here as normal routes */}
<Route
path="/idontneednavbar"
element={<ProtectedRoute component={ProviderRegistrationInfo} />}
/>
</Routes>
</>
);
function LayoutsWithNavbar() {
return (
<>
{/* Your navbar component */}
<Navbar />
{/* This Outlet is the place in which react-router will render your components that you need with the navbar */}
<Outlet />
{/* You can add a footer to get fancy in here :) */}
</>
);
}
How it works
The LayoutsWithNavbar
component will render the navbar with any component you need with a navbar. You can find an example in the official react-router v6 docs here: https://reactrouter.com/docs/en/v6/getting-started/overview#nested-routes
Learn more about the Outlet
component: https://reactrouter.com/docs/en/v6/getting-started/concepts#outlets
Yes, Daniel is correct, but to expand upon his answer, your primary app component would need to have a navbar component within it. That way, when you render the primary app (any page under the '/' path), it would also display the navbar. I am guessing that you wouldn't want your login page to display the navbar, so that shouldn't be a nested component, and should instead be by itself. So your routes would end up looking something like this:
<Router>
<Route path="/" component={App}>
<Route path="page1" component={Page1} />
<Route path="page2" component={Page2} />
</Route>
<Route path="/login" component={Login} />
</Router>
And the other components would look something like this:
var NavBar = React.createClass({
render() {
return (
<div>
<ul>
<a onClick={() => history.push('page1') }>Page 1</a>
<a onClick={() => history.push('page2') }>Page 2</a>
</ul>
</div>
)
}
});
var App = React.createClass({
render() {
return (
<div>
<NavBar />
<div>Other Content</div>
{this.props.children}
</div>
)
}
});
Note The accepted is perfectly fine - but wanted to add a version4 example because they are different enough.
Nav.js
import React from 'react';
import { Link } from 'react-router';
export default class Nav extends React.Component {
render() {
return (
<nav className="Nav">
<div className="Nav__container">
<Link to="/" className="Nav__brand">
<img src="logo.svg" className="Nav__logo" />
</Link>
<div className="Nav__right">
<ul className="Nav__item-wrapper">
<li className="Nav__item">
<Link className="Nav__link" to="/path1">Link 1</Link>
</li>
<li className="Nav__item">
<Link className="Nav__link" to="/path2">Link 2</Link>
</li>
<li className="Nav__item">
<Link className="Nav__link" to="/path3">Link 3</Link>
</li>
</ul>
</div>
</div>
</nav>
);
}
}
App.js
import React from 'react';
import { Link, Switch, Route } from 'react-router';
import Nav from './nav';
import Page1 from './page1';
import Page2 from './page2';
import Page3 from './page3';
export default class App extends React.Component {
render() {
return (
<div className="App">
<Router>
<div>
<Nav />
<Switch>
<Route exactly component={Landing} pattern="/" />
<Route exactly component={Page1} pattern="/path1" />
<Route exactly component={Page2} pattern="/path2" />
<Route exactly component={Page3} pattern="/path3" />
<Route component={Page404} />
</Switch>
</div>
</Router>
</div>
);
}
}
Alternatively, if you want a more dynamic nav, you can look at the excellent v4 docs: https://reacttraining.com/react-router/web/example/sidebar
Edit
A few people have asked about a page without the Nav, such as a login page. I typically approach it with a wrapper Route component
import React from 'react';
import { Link, Switch, Route } from 'react-router';
import Nav from './nav';
import Page1 from './page1';
import Page2 from './page2';
import Page3 from './page3';
const NavRoute = ({exact, path, component: Component}) => (
<Route exact={exact} path={path} render={(props) => (
<div>
<Header/>
<Component {...props}/>
</div>
)}/>
)
export default class App extends React.Component {
render() {
return (
<div className="App">
<Router>
<Switch>
<NavRoute exactly component={Landing} pattern="/" />
<Route exactly component={Login} pattern="/login" />
<NavRoute exactly component={Page1} pattern="/path1" />
<NavRoute exactly component={Page2} pattern="/path2" />
<NavRoute component={Page404} />
</Switch>
</Router>
</div>
);
}
}