Always visible components in React Router refer to components that are displayed on every page of the application regardless of the route or URL. These components can include a header, footer, navigation bar, or any other UI elements that you want to be visible at all times.
In a React Router application, the router component is responsible for rendering the appropriate component based on the current URL or route. By wrapping the routes in a container component that includes the always visible components, we can ensure that these components are displayed on every page of the application.
In this lesson, we will learn how to create always visible components in our application.
So, as per the latest release of React Router, if you want to show some common components for certain routes, you should create something called an app shell. Now that "app shell" is really nothing more than a layout with a pathless route.
So, let's start with the implementation.
For that, we will create a new file called Header.tsx
in the src/components
folder of our smarter-tasks
project.
In the Header.tsx
file, add the following code to create a simple header component with navigation for the routes we created.
const Header = () => {
return (
<nav className="bg-gray-800 py-4">
<div className="mx-auto px-4">
<div className="flex justify-between">
<div className="flex items-center w-1/3">
<a href="/home" className="ml-6 text-gray-300 hover:text-white">
Home
</a>
<a href="/tasks" className="ml-6 text-gray-300 hover:text-white">
Tasks
</a>
</div>
<div className="flex items-center w-1/3 justify-center">
<h2 className="text-white text-lg font-bold">Smarter Tasks</h2>
</div>
</div>
</div>
</nav>
);
};
export default Header;
So, we'll create a new component called Layout.tsx
inside our src
directory.
import Header from './components/Header';
const Layout = () => {
return (
<>
<Header />
<main>
{/* We want route specific content to show up in this position */}
</main>
</>
)
}
export default Layout;
So, Layout
is nothing but a simple component, right? But I've kept a placeholder where I want to show some route specific content. How we will do that, we will figure out later.
For that, we will import the Layout
component in App.tsx
file and use it in our route definition.
import {
createBrowserRouter,
RouterProvider,
} from "react-router-dom";
import HomePage from './pages/HomePage';
import TaskListPage from './pages/TaskListPage';
import TaskDetailsPage from "./pages/TaskDetailsPage";
import Layout from "./Layout";
const router = createBrowserRouter([
{
element: (
<Layout />
),
children: [
{
path: "/",
element: (<HomePage />)
},
{
path: "tasks",
element: (<TaskListPage />)
}
]
}
]);
const App = () => {
return (
<RouterProvider router={router} />
);
}
export default App
Here, I've defined all of our routes (like: homepage, tasks page etc.) as child route of <Layout>
component. And that's how our <Layout>
is acting as an app shell for all other routes.
Now let's head back to browser to check if it's working or not.
Action: Open http://localhost:5173/ in browser.
So as you can see, the Header component is showing up perfectly, and using the links we can gavigate to Home and Tasks page as well. But something is wrong here, where are our content for Home and Tasks page?
So to fix it, we will use a special component called, Outlet
from the react-router-dom library. Outlet
is primarily used in nested route configurations to define the location where child components should be rendered.
So, in our Layout.tsx
file, first we will simply import Outlet
from the react-router-dom
library.
import { Outlet } from "react-router-dom"
import Header from './components/Header';
const Layout = () => {
return (
<>
<Header />
<main>
<Outlet />
</main>
</>
)
}
export default Layout;
Then we've simply used Outlet
inside the main
.
So, let's go back to the browser once again,
Action: Open http://localhost:5173/ in browser. And yes, this time it's working as expected.
When we navigate to any page of our application, the Header
component will be visible.
So, we have successfully created always visible components using React Router, in our project. We can use this approach to create any component that we want to be always visible, such as a footer or a sidebar etc.
See you in the next one!