qwe*_*ezz 6 typescript reactjs react-router react-router-dom
我试图在 React Router 6.4.3 中从 BrowserRoute 组件切换到 createBrowserRouter 但出现错误:
useNavigate() 只能在组件上下文中使用。
我该如何解决这个问题?该错误来自 AuthProvider 组件,我认为我需要用 RouterProvider 包装它,但不清楚如何做到这一点。
Index.tsx 组件
const container = document.getElementById('root')!;
const root = createRoot(container);
root.render(
<React.StrictMode>
<Provider store={store}>
<AuthProvider>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</AuthProvider>
</Provider>
</React.StrictMode>
);
Run Code Online (Sandbox Code Playgroud)
App.tsx 组件
const router = createBrowserRouter([
{
element: <ProtectedRoute />,
children: [
{
path: '/',
element: <DashboardLayout />,
children: [
{
index: true,
element: <HomePage />,
},
{
path: 'about',
element: <AboutPage />,
},
],
},
],
},
{
path: '/auth',
element: <Auth />,
},
]);
const App = () => {
const { isLoading } = useAuth0();
if (isLoading) {
return <LoaderPage />;
}
return (
<>
<Box>
<CssBaseline />
<RouterProvider router={router} />
</Box>
</>
);
};
Run Code Online (Sandbox Code Playgroud)
错误来自 AuthProvider.tsx
export const AuthProvider = ({ children }: PropsWithChildren<Auth0ProviderWithConfigProps>): JSX.Element | null => {
const domain = process.env.REACT_APP_AUTH0_DOMAIN;
const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID;
const navigate = useNavigate();
if (!(domain && clientId)) {
return null;
}
const onRedirectCallback = (appState: any) => {
navigate(appState?.returnTo || window.location.pathname);
};
return (
<Auth0Provider
domain={domain}
clientId={clientId}
redirectUri={window.location.origin}
onRedirectCallback={onRedirectCallback}
>
{children}
</Auth0Provider>
);
};
Run Code Online (Sandbox Code Playgroud)
UPD
受保护的路由.tsx
export const ProtectedRoute: React.FC = () => {
const location = useLocation();
const { isAuthenticated } = useAuth0();
return isAuthenticated? <Outlet /> : <Navigate to="/auth" state={{ from: location }} replace />;
};
Run Code Online (Sandbox Code Playgroud)
如果我回滚,请将这些组件更改为支持 BrowserRouter,然后一切正常:
索引.tsx
root.render(
<React.StrictMode>
<BrowserRouter>
<AuthProvider>
<Provider store={store}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</Provider>
</AuthProvider>
</BrowserRouter>
</React.StrictMode>
);
Run Code Online (Sandbox Code Playgroud)
应用程序.tsx
const App = () => {
const { isLoading } = useAuth0();
const routes = useRoutes([
{
element: <ProtectedRoute />,
children: [
{
path: '/',
element: <DashboardLayout />,
children: [
{
index: true,
element: <HomePage />,
},
{
path: 'about',
element: <AboutPage />,
},
],
},
],
},
{
path: '/auth',
element: <Auth />,
},
]);
if (isLoading) {
return <LoaderPage />;
}
return (
<>
<Box>
<CssBaseline />
{routes}
</Box>
</>
);
};
Run Code Online (Sandbox Code Playgroud)
Codesandbox: https://codesandbox.io/s/nice-morning-oxwwj6?file=/src/ App.tsx
该AuthProvider
组件需要在路由上下文中呈现,以便访问它并使用任何钩子react-router-dom
。AuthProvider
创建一个渲染组件包装的布局路线Outlet
。
例子:
import {
createBrowserRouter,
Outlet
} from 'react-router-dom';
const AuthLayout = () => (
<AuthProvider>
<Outlet />
</AuthProvider>
);
const router = createBrowserRouter([
{
element: <AuthLayout />,
children: [
{
element: <ProtectedRoute />,
children: [
{
path: '/',
element: <DashboardLayout />,
children: [
{
index: true,
element: <HomePage />,
},
{
path: 'about',
element: <AboutPage />,
},
],
},
],
},
{
path: '/auth',
element: <Auth />,
},
]
},
]);
const App = () => {
const { isLoading } = useAuth0();
if (isLoading) {
return <LoaderPage />;
}
return (
<>
<Box>
<CssBaseline />
<RouterProvider router={router} />
</Box>
</>
);
};
Run Code Online (Sandbox Code Playgroud)
...
const container = document.getElementById('root')!;
const root = createRoot(container);
root.render(
<React.StrictMode>
<Provider store={store}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</Provider>
</React.StrictMode>
);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5859 次 |
最近记录: |