🔐 Private Route in React Router v6

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 now Navigate
  • 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

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!

secure

Created At
9/21/2021
Updated At
3/10/2023
Published At
9/21/2021