我正在使用 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
的数据路由器
我进行了很多搜索,但找不到任何东西可以解决我的问题。 谁能帮我?谢谢你。
如果
是渲染路由器上下文的组件,则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')
);