Reputation: 13
Here is the error that I get once I run the application.
ERROR in ./node_modules/@okta/okta-react/bundles/okta-react.esm.js 284:14-27
export ‘useRouteMatch’ (imported as ‘useRouteMatch’) was not found in ‘react-router-dom’ (possible exports: BrowserRouter, HashRouter, Link, MemoryRouter, NavLink, Navigate, Outlet, Route, Router, Routes, UNSAFE_LocationContext, UNSAFE_NavigationContext, UNSAFE_RouteContext, createRoutesFromChildren, createSearchParams, generatePath, matchPath, matchRoutes, renderMatches, resolvePath, unstable_HistoryRouter, useHref, useInRouterContext, useLinkClickHandler, useLocation, useMatch, useNavigate, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams)
Here is what my code looks like in my Index.tsx file.
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import "mdb-react-ui-kit/dist/css/mdb.min.css";
import { Security } from "@okta/okta-react";
import { OktaAuth } from "@okta/okta-auth-js";
const config = {
clientId: "*********************",
issuer: "https://****************/oauth2/default",
redirectUri: "http://localhost:3000/login/callback",
scopes: ["openid", "profile", "email"],
pkce: true,
};
const oktaAuth = new OktaAuth(config);
const restoreOriginalUri = () => {
// Callback function to restore URI during login
};
ReactDOM.render(
<React.StrictMode>
<Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
<App />
</Security>
</React.StrictMode>,
document.getElementById("root")
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more:
reportWebVitals();
Upvotes: 1
Views: 4117
Reputation: 21
I encountered the same problem, but here is my workaround.
First of all, this is not an official way, since react-router v6 is still not supported by okta. But with a few tricks it is possible to get okta-react running with react-router v6.
First you have to add the new <BrowserRouter>
Tag in your index.js file:
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
After you have done that, you have to create a new component for secured routes. This component is quite simple, because it just checks if a user is logged in. If that is not the case you will be redirected to the login page. The check will be done with a hook provided by the okta-react library. We will setup the library later.
PrivateRoutes.js
import { Outlet, Navigate } from "react-router-dom";
import { useOktaAuth } from '@okta/okta-react';
const PrivateRoutes = () => {
const { authState } = useOktaAuth();
if(!authState) {
return <div>Loading...</div>;
}
return (
authState.isAuthenticated ? <Outlet /> : <Navigate to="/login"/>
);
}
export default PrivateRoutes;
The last part is the App.js file. In this file we will setup the okta-react library and configure private and public routes. With the update from reacr-router v5 to react-router v6 quite a few things changed. If you want to know what changed and how that works I recomend the following article:
react-router v5 -> v6 migration guide
Important in the App.js file is, that <Security>
Tag is wrapped around the <Routes>
tag. Since the <Routes>
Tag can only have <Route>
Children (nested is possible but they have to be <Route>
-Tags). A good tutorial for the private Routes in react-router v6 is the following Video (which provides the base for this post):
react-router v6 protected routes
The OktaAuth-Component is configured just like the official guide from okta describes it. The useHistory()-Stuff from react-router v5 is updated to useNavigate() from react-router v6. Here is my full App.js file:
App.js
import { Route, Routes, useNavigate } from 'react-router-dom';
import PrivateRoutes from './components/PrivateRoutes';
import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js';
import { LoginCallback, Security } from '@okta/okta-react';
import Test from './pages/Test';
import Home from './pages/Home';
import Login from './pages/Login';
import './App.css';
const oktaAuth = new OktaAuth({
issuer: process.env.REACT_APP_OKTA_ISSUER,
clientId: process.env.REACT_APP_OKTA_CLIENT_ID,
redirectUri: window.location.origin + '/login/callback'
});
function App() {
const navigate = useNavigate();
const restoreOriginalUri = async (_oktaAuth, originalUri) => {
navigate(toRelativeUrl(originalUri || '/login', window.location.origin), {replace: true});
}
return (
<div className="App">
<Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri} >
<Routes>
<Route element={ <PrivateRoutes />}>
{/* PRIVATE_ROUTES_BEGIN */}
<Route element={ <Home /> } path="/" exact/>
<Route element={ <Test /> } path="/test"/>
{/* PRIVATE_ROUTES_END */}
</Route>
<Route element={ <Login /> } path="/login"/>
<Route element={ <LoginCallback />} path="/login/callback"/>
</Routes>
</Security>
</div>
);
}
export default App;
Keep in mind, that the element of the new Route
in react-router v6 takes HTML-Tags not just the "name" of the component
I hope this was kind of usefull. Again this is not the official way, but I did some testing to this topic and it works quite well for me. I still hope that okta releases official react-router v6 support in some time :)
Upvotes: 2
Reputation: 2709
I will go on a hunch and assume that you use newer react-router version than v5.
As per https://github.com/okta/okta-react/issues/187
@okta/okta-react currently only supports react-router v5. We are currently investigating v6 support
Upvotes: 1