Auth0によるページの保護をReact Router v5からv6に変更

次のコードが、react-router-domをv5からv6にアップグレードしたら、動かなくなりました(主題に無関係のコードもそのまま載せています)。

// App.jsx

import React, { useEffect } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import FooterMenu from './components/FooterMenu';
import { ThemeProvider } from 'styled-components';
import { StyledApp } from './styled/StyledApp';
import { GlobalStyle } from './styled/Global';
import { lightTheme, darkTheme } from './styled/Themes';
import useTheme from './hooks/useTheme';
import HomePage from './pages/HomePage';
import WorkshopPage from './pages/WorkshopPage';
import AboutPage from './pages/AboutPage';
import Navber from './components/Navbar';
import ProtectedRoute from './components/route/ProtectedRoute';
import toast, { Toaster } from 'react-hot-toast';

function App() {
  const [theme, toggleTheme] = useTheme();
  const currentTheme = theme === 'light' ? lightTheme : darkTheme;
  useEffect(() => {
    const ua = window.navigator.userAgent.toLowerCase();
    if (ua.indexOf('safari') > 1 && ua.indexOf('chrome') === -1) {
      toast.error(
        'Safariはサポートされていません。ChromaかFirefoxを使用してください。',
        {
          icon: '😇',
        }
      );
    }
  }, []);

  return (
    <Router>
      <ThemeProvider theme={currentTheme}>
        <GlobalStyle />
        <StyledApp>
          <Toaster />
          <Navber toggleTheme={toggleTheme} />
          <Switch>
            <Route path='/about' component={AboutPage} />
            <ProtectedRoute path='/workshop' component={WorkshopPage} />
            <Route path='/' component={HomePage} />
          </Switch>
          <FooterMenu />
        </StyledApp>
      </ThemeProvider>
    </Router>
  );
}

export default App;

ここで、ProtectedRoute は次としていました。

// ProtectedRoute.jsx

import React from 'react';
import { Route } from 'react-router-dom';
import { withAuthenticationRequired } from '@auth0/auth0-react';

const ProtectedRoute = ({ component, ...args }) => (
  <Route component={withAuthenticationRequired(component)} {...args} />
);

export default ProtectedRoute;

これをやめて、次のRequireAuthに変更しました。

// RequireAuth.jsx


import React from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import LoginButton from '../LoginButton';

const RequireAuth = ({ children }) => {
  const { isAuthenticated } = useAuth0();
  return isAuthenticated ? (
    children
  ) : (
    <div>
      <p>Twitter認証がされていないとこのページは見ることができません。</p>
      <LoginButton />
    </div>
  );
};

export default RequireAuth;

App.jsx は次に変更しました。

// App.jsx


import React, { useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import FooterMenu from './components/FooterMenu';
import { ThemeProvider } from 'styled-components';
import { StyledApp } from './styled/StyledApp';
import { GlobalStyle } from './styled/Global';
import { lightTheme, darkTheme } from './styled/Themes';
import useTheme from './hooks/useTheme';
import HomePage from './pages/HomePage';
import WorkshopPage from './pages/WorkshopPage';
import AboutPage from './pages/AboutPage';
import Navber from './components/Navbar';
import RequireAuth from './components/route/RequireAuth';
import toast, { Toaster } from 'react-hot-toast';

function App() {
  const [theme, toggleTheme] = useTheme();
  const currentTheme = theme === 'light' ? lightTheme : darkTheme;
  useEffect(() => {
    const ua = window.navigator.userAgent.toLowerCase();
    if (ua.indexOf('safari') > 1 && ua.indexOf('chrome') === -1) {
      toast.error(
        'Safariはサポートされていません。ChromaかFirefoxを使用してください。',
        {
          icon: '😇',
        }
      );
    }
  }, []);

  return (
    <Router>
      <ThemeProvider theme={currentTheme}>
        <GlobalStyle />
        <StyledApp>
          <Toaster />
          <Navber toggleTheme={toggleTheme} />
          <Routes>
            <Route path='/about' element={<AboutPage/>} />
            <Route path='/workshop' element={<RequireAuth><WorkshopPage /></RequireAuth>} />
            <Route path='/' element={<HomePage/>} />
          </Routes>
          <FooterMenu />
        </StyledApp>
      </ThemeProvider>
    </Router>
  );
}

export default App;

この実装はAuth0に依存しているので、カスタムフックを使って更に改良していく予定です。