Okta 和 React-router 6 useBlocker 不兼容

问题描述 投票:0回答:1

我正在使用 okta 来保护我的网站,该网站使用 React Route v5。 现在,我想更新到 React Route v6

首先,我尝试了这个并收到错误:“useBlocker 必须在数据路由器内使用”

  ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

function App() {
      const navigate = useNavigate();
      const restoreOriginalUri = (_oktaAuth: any, originalUri: string) => {
        navigate(toRelativeUrl(originalUri || "/", window.location.origin));
      };
    
      return (
        <Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
          <AppRoutes />
        </Security>
      );
    }
    
    const AppRoutes = () => {
      return (
        <Routes>          
          <Route path="login/callback" element={<LoginCallback />} />
          <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
          </Route>
        </Routes>
      );
    };
    
    
    const About = () => {
      let blocker = useBlocker(({ currentLocation, nextLocation }) => true);
    
      return (
        <div>
          About Page
          {blocker.state === "blocked" ? (
            <div>
              <p>Are you sure you want to leave?</p>
              <button onClick={() => blocker.proceed()}>Proceed</button>
              <button onClick={() => blocker.reset()}>Cancel</button>
            </div>
          ) : null}
        </div>
      );
}

然后,我通过以下更改更新了代码:

ReactDOM.render(
   <React.StrictMode>
     <App />
   </React.StrictMode>,
   document.getElementById('root')
);

 const AppRoutes = () => {
  const router = createBrowserRouter(
    createRoutesFromElements(
      <Route>
        <Route path="login/callback" element={<LoginCallback />} />
        <Route path="/" element={<Home />}>
          <Route path="/about" element={<About />} />
        </Route>
      </Route>
    )
  );

  return <RouterProvider router={router} />;
};

并遇到其他问题:“useNavigate() 只能在组件的上下文中使用”

我需要删除

BrowserRouter
,因为我需要一个用于
useBlocker

的数据路由器

我进行了很多搜索,但找不到任何东西可以解决我的问题。 谁能帮我?谢谢你。

react-router react-router-dom okta
1个回答
0
投票

如果

是渲染路由器上下文的组件,则 App 组件本身不能使用任何 React-Router 钩子。将 App 组件的主体逻辑抽象为在
路由器上下文中呈现的布局路由。
仅供参考,在其他 React 组件中定义 React 组件是一种 React 反模式,例如

AppRoutes

About
应单独声明,这样就不会在
App
的每个渲染周期重新创建它们。
import { useBlocker } from 'react-router-dom';

const About = () => {
  const blocker = useBlocker(({ currentLocation, nextLocation }) => true);

  return (
    <div>
      About Page
      {blocker.state === "blocked" ? (
        <div>
          <p>Are you sure you want to leave?</p>
          <button onClick={() => blocker.proceed()}>Proceed</button>
          <button onClick={() => blocker.reset()}>Cancel</button>
        </div>
      ) : null}
    </div>
  );
};

import {
  Outlet,
  useNavigate
} from 'react-router-dom';

const AppLayout = () => {
  const navigate = useNavigate();

  const restoreOriginalUri = (_oktaAuth: any, originalUri: string) => {
    navigate(toRelativeUrl(originalUri || "/", window.location.origin));
  };
    
  return (
    <Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
      <Outlet />
    </Security>
  );
};
import {
  createBrowserRouter,
  createRoutesFromElements,
  RouterProvider,
  Route,
} from 'react-router-dom';

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route>
      <Route element={<AppLayout />}>
        <Route path="login/callback" element={<LoginCallback />} />
        <Route path="/" element={<Home />}>
          <Route path="/about" element={<About />} />
        </Route>
      </Route>
    </Route>
  )
);

function App() {
  return <RouterProvider router={router} />;
}
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
© www.soinside.com 2019 - 2024. All rights reserved.