When building more complex React apps
with Routing, it's quite common that some routes should also
have shared layout elements.
For example, this main navigation bar here at the top,
should probably be visible on all routes we have.
And to achieve this, you can add so-called layout routes.
Which are actually just normal routes
but routes that nest other routes inside of them.
To add such a layout route,
we could add a new route definition.
The position in the array doesn't really matter here
but I'll add it as the first route.
And then here the path is still / nothing,
because I want to create a layout that wraps all routes
no matter which path they have.
Then we have to add an element and here,
I need to add a new component.
And for that I'll actually add a new folder, called routes,
to organize my components differently now.
The components which are used as routes,
should go into the routes folder,
and the other components which are used somewhere else,
will stay in the components folder.
This is not needed technically,
but makes this app a bit easier to maintain and understand.
In this routes folder, I'll add a RootLayout.jsx file,
though the file name, of course, is up to you.
In there, we create a regular component function,
which could be called RootLayout,
and which is of course exported.
And then here, I wanna return a fragment
where I have my MainHeader,
and then something else which I'll add soon.
For the moment, it's just a MainHeader.
And that should be a layout route which is wrapped around
other routes so that the MainHeader is shared
and then the content of the upper routes
is rendered below this MainHeader.
To make this work, back in main.jsx,
we can import the RootLayout route from routes/RootLayout,
and set this as an element here like this.
And now the important part that must be added here,
to make this a layout route, is that we add another key
to the route definition.
And that's the children key, which takes an array
and it takes an array of more route definitions.
And here, I'll then move these two route definitions
into this RootLayout route definition.
And that turns this RootLayout route definition
into a layout route of these two routes.
Because these two routes are now nested routes
to this route here, and they share the layout provided
by that route.
They simply are inserted into this RootLayout component,
and therefore they share this MainHeader.
However, if we save this you see that, yeah,
the header is there, but the content is missing,
and clicking New Post also doesn't do anything.
The reason for that is that indeed,
we are now sharing this MainHeader component,
but we're not telling react-router where
to render the content of these nested routes.
And that is of course, something we should do.
And we do that by going to the RootLayout
and importing an Outlet component from react-router-dom.
That's a special component provided by
the react-router package, which should be rendered
in the place where the actual nested route content
should be rendered, should be injected, so to say.
So this is simply a placeholder where
the nested routes can render their content
in the RootLayout.
And therefore with Outlet added here,
in RootLayout, below the MainHeader,
if we save this, we now got the app component content back.
And therefore, I now also have two headers here,
because at the moment, the App component, of course,
still brings its own MainHeader.
But that's what we can tackle next.
It's now time to refactor the code a little bit
and clean it up a little bit to make sure
that we don't have this duplicate header here, for example.