I am attempting to implement a protected route in my React web application, but I am receiving an error message: Uncaught Error: [ProtectedRoute] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>.
In my application, I want to display a login popup for users when they first open the app if they have not yet signed in. However, I encountered a problem where users were able to access the page without signing in, so I tried to implement a protected router to prevent this and encounter with the error.
App.jsx
function App() {
return (
<>
<div className="app">
<Navigation />
<Routes>
<ProtectedRoute path="/" element={<Home/>} />
<ProtectedRoute path="/about" element={<About/>} />
<ProtectedRoute path="/dashboard" element={<Dashboard/>} />
<ProtectedRoute path="/explore" element={<Explore/>} />
</Routes>
</div>
</>
);
}
export default App;
ProtectedRoute.jsx
import React, { useEffect, useState } from 'react';
import { Route, Navigate } from 'react-router-dom';
import { useMsal, useIsAuthenticated } from '@azure/msal-react';
function ProtectedRoute({ element: Component, ...rest }) {
const { instance } = useMsal();
const isAuthenticated = useIsAuthenticated();
const [popupOpened, setPopupOpened] = useState(false);
useEffect(() => {
const handleLogin = async () => {
try {
const account = await instance.handleRedirectPromise();
if (account) {
setPopupOpened(false);
}
} catch (e) {
console.error(e);
}
const accounts = instance.getAllAccounts();
if (!isAuthenticated && !popupOpened && accounts.length === 0) {
try {
await instance.loginPopup();
setPopupOpened(true);
} catch (e) {
console.error(e);
}
}
};
handleLogin();
}, [instance, isAuthenticated, popupOpened]);
if (isAuthenticated) {
return <Route {...rest} element={<Component />} />;
}
return <Navigate to="/login" replace />;
}
export default ProtectedRoute;
index.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
import { BrowserRouter } from 'react-router-dom';
import { PublicClientApplication } from '@azure/msal-browser';
import { MsalProvider } from '@azure/msal-react';
import { msalConfig } from './services/Config.js';
const msalInstance = new PublicClientApplication(msalConfig);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<MsalProvider instance={msalInstance}>
<BrowserRouter>
<App />
</BrowserRouter>
</MsalProvider>
</React.StrictMode>
);