Search code examples
reactjsreact-routergatsbyreact-router-domauth0

Migrate from react-router to react router v6


I am trying to complete this tutorial Securing Gatsby With Auth0, but have hit a roadblock due to reach/router not being compatible with react 17. After a bit of googling around, I found this issue Which router project to use moving forward which has a migration guide: Migrate to React Router from Reach

However, as a beginner, I am not well versed enough to make sense of what it contains.

The source code from the tutorial is as follows:

import React from "react"
import { Router } from "@reach/router"
import { Link } from "gatsby"

const Home = () => <p>Home</p>
const Settings = () => <p>Settings</p>
const Billing = () => <p>Billing</p>

const Account = () => (
  <>
    <nav>
      <Link to="/account">Home</Link>{" "}
      <Link to="/account/settings">Settings</Link>{" "}
      <Link to="/account/billing">Billing</Link>{" "}
    </nav>
    <Router>
      <Home path="/account" />
      <Settings path="/account/settings" />
      <Billing path="/account/billing" />
    </Router>
  </>
)

export default Account

From the migration guide update router to routes, I have changed this to:

import React from "react"
import { Link } from "gatsby"
import { Routes } from "react-router-dom";

const Home = () => <p>Home</p>
const Settings = () => <p>Settings</p>
const Billing = () => <p>Billing</p>

const Account = () => (
  <>
    <nav>
      <Link to="/account">Home</Link>{" "}
      <Link to="/account/settings">Settings</Link>{" "}
      <Link to="/account/billing">Billing</Link>{" "}
    </nav>
    <Routes>
      <Home path="/account" />
      <Settings path="/account/settings" />
      <Billing path="/account/billing" />
    </Routes>
  </>
)

export default Account

So in essence, replace Router with Routes. Now this compiles successfully, but fails at run time with this error:

[Home] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>

So Home, Settings, and Billing are deemed not to be <Route\> or <React.Fragment\>

This is a simple example, for somebody well versed in react-router. I am just learning this stuff so having some difficulty. I have asked auth0 to update this tutorial but have no idea when this will be actioned, if ever.


Solution

  • The Routes component only replaces the Switch component from react-router-dom v5, but is required to wrap Route components in v6. The routed components, Home, etc... need to be rendered by a Route.

    import React from "react"
    import { Link } from "gatsby"
    import { Routes } from "react-router-dom";
    
    const Home = () => <p>Home</p>
    const Settings = () => <p>Settings</p>
    const Billing = () => <p>Billing</p>
    
    const Account = () => (
      <>
        <nav>
          <Link to="/account">Home</Link>{" "}
          <Link to="/account/settings">Settings</Link>{" "}
          <Link to="/account/billing">Billing</Link>{" "}
        </nav>
        <Routes>
          <Route path="/account" element={<Home />} />
          <Route path="/account/settings" element={<Settings />} />
          <Route path="/account/billing" element={<Billing />} />
        </Routes>
      </>
    );