# Composing `` in React Router v6 Composition of `` elements in React Router is changing in v6 from how it worked in v4/5 and in [Reach Router](https://reach.tech/router/). React Router v6 is the successor of both React Router v5 and Reach Router. This document explains our rationale for making the change as well as a pattern you will want to avoid in v6 and a note on how you can start preparing your v5 app for v6 today. ## Background In React Router v5, we had [an example of how you could create a `` element](https://github.com/remix-run/react-router/blob/320be7afe44249d5c025659bc00c3276a19f0af9/packages/react-router-dom/examples/Auth.js#L50-L52) to restrict access to certain routes on the page. This element was a simple [wrapper around an actual `` element](https://github.com/remix-run/react-router/blob/320be7afe44249d5c025659bc00c3276a19f0af9/packages/react-router-dom/examples/Auth.js#L140-L154) that made a simple decision: is the user authenticated or not? If so, render the `children` prop. Otherwise, render a `` to the login page. It looked something like this: ```tsx import { Switch, Route, Redirect } from "react-router-dom"; function App() { return ( ); } function PrivateRoute({ path, children, redirectTo }) { let isAuthenticated = getAuth(); return ( ( isAuthenticated ? children : )} /> ); } ``` When it came time to render, the `` would treat your `` component the same as a normal `` element. But did you ever wonder how it worked? Here's a short explanation: The interesting thing about `` in React Router v5 is that, unlike most React components, it uses the props of its `children` to decide which ones to render. This is a little non-standard, but `children` is just a prop after all. So it's not too different from deciding what to render based on any other prop you receive. In the case of ``, it actually looks through the `path`s of all its `children` to figure out which ones match the current URL, and then it renders the ones that do. If you were using Reach Router, The `` component worked similarly to v5's ``. Except it took this one step further and eliminated the `` component altogether and just used your own custom components instead for convenience. ## The Problem The problem is that when you create a wrapper around a `` element, whether it's a v5-style `` component or a Reach Router custom component, **these components must expect all the props of `` in addition to any other props they receive**. This becomes particularly painful if you're using TypeScript (or `propTypes`, remember those?) to declare the types of props your components may receive. In the case of our `` component above, the TypeScript declaration for its props would be a union of its own props, and those of ``: ```tsx type ProtectedRouteProps = { redirectTo: string; }; function ProtectedRoute(props: RouteProps & ProtectedRouteProps) { // ... } ``` The problem was even more apparent when using TypeScript with Reach Router where you didn't have a `` component and every one of your custom route components was required to accept all route props as well as its own. ```tsx import { Router } from "@reach/router"; function App() { return ( ); } function HomePage(props: RouteProps & HomePageProps) { // ... } function AboutPage(props: RouteProps & AboutPageProps) { // ... } ``` Not only is the props type declaration messy, but in the majority of cases **your route components are receiving props that they don't actually do anything with**. Why? Because these props were meant for ``, not them. ## `` Composition in React Router v6 React Router v6 introduces a new `` element that replaces ``. One of the main advantages of `` over `` is its ability to understand nested `` elements, much like we did in React Router v3. We'll write more about just how cool `` is in the official v6 docs. In v6, `` is a lot more strict than it was in v5. Instead of building wrappers for ``, it may be used only inside other `` or `` elements. **If you try to wrap a `` in another component like `PrivateRoute` it'll throw an error**. ```tsx function PrivateRoute(props) { // BAD. This will throw in v6! return ; } ``` Instead of creating wrappers for your `` elements to get the functionality you need, you should do all your own composition in the `` prop. Taking the example from above, if you wanted to protect certain routes from non-authenticated users in React Router v6, you could do something like this: ```tsx import { Routes, Route, Navigate } from "react-router-dom"; function App() { return ( } /> . // This is really just inverting the wrapping, but it's a lot // more clear which components expect which props. } /> ); } function RequireAuth({ redirectTo, children }) { let isAuthenticated = getAuth(); return isAuthenticated ? children : ; } ``` Notice how in this example the `RequireAuth` component doesn't expect any of ``'s props. This is because it isn't trying to act like a ``. Instead, it's just being rendered **inside** a ``. ## Get Started Upgrading Today If you want to get a head start on upgrading your React Router v5 app to v6 today, you can eliminate any custom route components in your ``es and just use plain ``s instead. Then, do your composition inside the `` prop. When you finally do upgrade to v6, convert ` ...}>` to ``.