Things are changing fast in WEB today, and react-router
v6 is in beta already and around the corner. π€
This is just for learning purposes only, react-router v6 is still in beta, use at your own risk
Private routes in v5 and below were done in a specific way using a custom component mostly named PrivateRoute
that was most of the times just a wrapper and composition of basic Route
and Redirect
e.g.
function PrivateRoute(props) {
let { component: Component, children, render, ...rest } = props
let auth = useAuth();
return (
<Route
{...rest}
render={() => auth
? <Component />
: <Redirect to="/login" />
}
/>
);
}
function App() {
return (
<BrowserRouter>
<Route path="/" component={Public} />
<PrivateRoute path="/private" component={Private} />
</BrowserRouter>
);
}
But taking a look at v6 docs it seems that things changed a little bit, and we need to think a little bit different about it.
For info about all API reference see the link
Let's move on.
Some things that we used to create PrivateRoute
have changed a little bit
-
Redirect
is nowNavigate
-
Route
props changed and is just a stub component now - A new component
Routes
appearead
In v6, routes are rendered in such a manner
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Public />} />
<Route path="/private" element={<Private />} />
</Routes>
</BrowserRouter>
);
}
const Public = () => <div>public</div>;
const Private = () => <div>private</div>;
So as you can see, no more render props or component prop.
You need to pass a direct JSX element (don't worry about performance if you do)
Ok now let's take a look at Route
component source code
/**
* Declares an element that should be rendered at a certain URL path.
*
* @see https://reactrouter.com/api/Route
*/
export function Route(_props: RouteProps): React.ReactElement | null {
invariant(
false,
`A <Route> is only ever to be used as the child of <Routes> element, ` +
`never rendered directly. Please wrap your <Route> in a <Routes>.`
);
}
Wait a minute where is the code? π Well actually the parent component Routes
will use the Route
just as a host for the props and children, and do nothing more with the Route
For more info about
Routes
implementation see link
So how we do implement our PrivateRoute
now? π€ If we do some adjustments to PrivateRoute
props, it will look like this
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Public />} />
<PrivateRoute path="/private" element={<Private />} />
</Routes>
</BrowserRouter>
);
}
But this will not work. Routes
will just take the props of PrivateRoute
and ignore it's body totally. Even a console.log inside PrivateRoute
will not be shown.
So what we do? π€ We do some more adjustments to PrivateRoute
function PrivateRoute({ children }) {
const auth = useAuth();
return auth ? <>{children}</> : <Navigate to="/login" />;
}
As you can see we changed Redirect
to Navigate
, and just return children
if user is authenticated. And the usage of it also changes a little bit
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Public />} />
<Route
path="/private"
element={
<PrivateRoute>
<Private />
</PrivateRoute>
}
/>
</Routes>
</BrowserRouter>
);
}
As you can see PrivateRoute
also moves to element
prop.
The implementation of
PrivateRoute
can be done in multiple ways.
Here is a different implementation of PrivateRoute
using Outlet
function PrivateOutlet() {
const auth = useAuth();
return auth ? <Outlet /> : <Navigate to="/login" />;
}
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/private-outlet" element={<PrivateOutlet />}>
<Route element={<Private />} />
</Route>
</Routes>
</BrowserRouter>
);
}
The pros of this is that you can put multiple private sub routes under same route.
For a full example see this Codesandbox
That's all for today. Happy coding! π π β¨
Keep your users secure!
Cover Photo by Maxim Zhgulev on Unsplash
Top comments (61)
Awesome man! Huge thanks π
thanks
Awesome !
ΰ€Άΰ€Ύΰ€¨ΰ€¦ΰ€Ύΰ€° ΰ€²ΰ₯ΰ€ ΰ€ΰ€Ύΰ€
Great
Perfeito, muito obrigado (thank you)! But just aesthetic issues I recommend I created the component that manages private routes receiving props and your code is more reduced and clean.
component={Page} should be capital C component or should at lease be defined:
I was using a module to route users to I only need to render the header once etc.. so in I have outlet to render the nested routes. How can I now use the with the nested routes. This was my homeModule
And this is how I would want to have it work:
Whoops, I already figured it out, this was the code for my privateoutlet:
Yes π I was about to write that you need to change PrivateOutlet
is it necesary write Outlet twice?
How do you protect a set of routes using PrivateRoute?
Repeating ...
... is not very elegant.
Thank you!
Awesome very Good Brother! Many Many Thanks.
Nice πππ