I am using react-router-dom v6. Trying to authenticate user using oidc client and if authenticated the Private page should allow. However I am getting this error below. I am not sure what I am doing wrong. appreciate your inputs on this please.
Uncaught Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in
a . at invariant (history.ts:480:1) at Route (components.tsx:274:1) at renderWithHooks (react-dom.development.js:16305:1) at mountIndeterminateComponent (react-dom.development.js:20074:1) at beginWork (react-dom.development.js:21587:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at beginWork$1 (react-dom.development.js:27451:1) at performUnitOfWork (react-dom.development.js:26557:1)
The above error occurred in the <Route> component: at Route (http://localhost:3000/static/js/bundle.js:48027:78) at PrivateRoute (http://localhost:3000/static/js/bundle.js:426:14) at RenderedRoute (http://localhost:3000/static/js/bundle.js:47638:5) at Routes (http://localhost:3000/static/js/bundle.js:48103:5) at AuthProvider (http://localhost:3000/static/js/bundle.js:193:5) at Router (http://localhost:3000/static/js/bundle.js:48041:15) at BrowserRouter (http://localhost:3000/static/js/bundle.js:46238:5) at App
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( <App /> );
App.js
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import HomePage from './HomePage';
import Profile from './Profile';
import Login from './Login';
import {AuthProvider} from "./AuthProvider";
function App() {
return (
<Router>
<AuthProvider>
<Routes>
<Route exact path="/signin-oidc" element={<HomePage />} />
<Route
exact
path="/profile"
element={<PrivateRoute><Profile /></PrivateRoute>}
/>
<Route exact path="/" element={<HomePage /> } />
<Route exact path="/login" element={<Login />} />
</Routes>
</AuthProvider>
</Router>
);
}
export default App;
HomePage.js
export default function HomePage() {
return (
<div>home page</div>
)
}
Profile.js
export default function Profile() {
return (
<div>profile page</div>
)
}
Login.js
export default function Login() {
return (
<div>login page</div>
)
}
PrivateRoute.js
import React from "react";
import { Route, Navigate } from "react-router-dom";
import { useAuth } from "./AuthProvider";
export default function PrivateRoute({ element: Component, ...rest }) {
const { isAuthenticated } = useAuth();
return (
<Route
{...rest}
element={isAuthenticated
? (<Component />)
: (<Navigate to="/login" replace />)
}
/>
);
}
AuthProvider.js
import React, { createContext, useContext, useEffect, useState } from "react";
import { UserManager } from "oidc-client";
export const oidcConfig = {
authority: 'https://idp.myid.abcdef.com/.well-known/openid-configuration',
client_id: 'oidc-client-20230304-0001',
redirect_uri: 'http://localhost:3000/signin-oidc',
response_type: 'id_token token',
automaticSilentRenew: true,
loadUserInfo: true,
scope: 'openid profile email',
};
const userManager = new UserManager({ ...oidcConfig });
const AuthContext = createContext();
export function AuthProvider({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [user, setUser] = useState(null);
useEffect(() => {
const loadUserFromStorage = async () => {
const user = await userManager.getUser();
if (user) {
setIsAuthenticated(true);
setUser(user);
}
console.log(user)
};
loadUserFromStorage();
}, []);
const login = async () => {
console.log("in signin-redirect")
await userManager.signinRedirect();
};
const logout = async () => {
await userManager.signoutRedirect();
};
return (
<AuthContext.Provider
value={{ isAuthenticated, user, login, logout }}
>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
return useContext(AuthContext);
}