Vic*_*tor 8 reactjs react-router react-router-dom
使用 react-router 的新版本 6 编写 ProtectedRoute 的正确方法是什么?我写了这个,但它不是一条路线
const PrivateRoute = ({ component: Component, ...props }) => {
if (!Component) return null;
return props.isAuthenticated
? <Component />
: <Navigate to={props.redirectLink} /> }
export default PrivateRoute;
Run Code Online (Sandbox Code Playgroud)
Zet*_*Zet 73
我从以下位置获取了这个示例react-router-dom: https: //github.com/remix-run/react-router/blob/main/examples/auth/README.md
然后修改成这个https://stackblitz.com/edit/github-5kknft?file=src%2FApp.tsx
export default function App() {
return (
<AuthProvider>
<Routes>
<Route element={<Layout />}>
<Route path="/" element={<PublicPage />} />
<Route path="/public" element={<PublicPage />} />
<Route path="/login" element={<LoginPage />} />
<Route element={<RequireAuth />}>
<Route path="/protected" element={<ProtectedPage />} />
<Route path="/dashboard" element={<Dashboard />} />
</Route>
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
</AuthProvider>
);
}
Run Code Online (Sandbox Code Playgroud)
function RequireAuth() {
let auth = useAuth();
let location = useLocation();
if (!auth.user) {
// Redirect them to the /login page, but save the current location they were
// trying to go to when they were redirected. This allows us to send them
// along to that page after they login, which is a nicer user experience
// than dropping them off on the home page.
return <Navigate to="/login" state={{ from: location }} />;
}
return <Outlet />;
}
Run Code Online (Sandbox Code Playgroud)
won*_*suc 34
这是React Router 文档中的官方指南。
您应该在 prop 中完成所有自己的组合,而不是为
<Route>元素创建包装器来获取所需的功能<Route element>。以上面的示例为例,如果您想在 React Router v6 中保护某些路由免受未经身份验证的用户的攻击,您可以执行以下操作:
import { Routes, Route, Navigate } from "react-router-dom";
function App() {
return (
<Routes>
<Route path="/public" element={<PublicPage />} />
<Route
path="/protected"
element={
// Good! Do your composition here instead of wrapping <Route>.
// This is really just inverting the wrapping, but it's a lot
// more clear which components expect which props.
<RequireAuth redirectTo="/login">
<ProtectedPage />
</RequireAuth>
}
/>
</Routes>
);
}
function RequireAuth({ children, redirectTo }) {
let isAuthenticated = getAuth();
return isAuthenticated ? children : <Navigate to={redirectTo} />;
}
Run Code Online (Sandbox Code Playgroud)
请注意,在此示例中,
RequireAuth组件不需要任何 的<Route>props。这是因为它并不想表现得像<Route>. 相反,它只是在<Route>.
vig*_*esh 28
这是我使用useRoutes实现私有路由的工作示例。
应用程序.js
import routes from './routes';
import { useRoutes } from 'react-router-dom';
function App() {
const { isLoggedIn } = useSelector((state) => state.auth);
const routing = useRoutes(routes(isLoggedIn));
return (
<>
{routing}
</>
);
}
Run Code Online (Sandbox Code Playgroud)
路由.js
import { Navigate,Outlet } from 'react-router-dom';
const routes = (isLoggedIn) => [
{
path: '/app',
element: isLoggedIn ? <DashboardLayout /> : <Navigate to="/login" />,
children: [
{ path: '/dashboard', element: <Dashboard /> },
{ path: '/account', element: <Account /> },
{ path: '/', element: <Navigate to="/app/dashboard" /> },
{
path: 'member',
element: <Outlet />,
children: [
{ path: '/', element: <MemberGrid /> },
{ path: '/add', element: <AddMember /> },
],
},
],
},
{
path: '/',
element: !isLoggedIn ? <MainLayout /> : <Navigate to="/app/dashboard" />,
children: [
{ path: 'login', element: <Login /> },
{ path: '/', element: <Navigate to="/login" /> },
],
},
];
export default routes;
Run Code Online (Sandbox Code Playgroud)
这是我使用 React-router v6 beta 的最新工作实现。我不知道如何使用 useRoutes 实现受保护的路由。他们的文档应该添加一个关于如何以两种方式实现受保护/私有路由的示例。
受保护的路由组件
import React from 'react';
import PropTypes from 'prop-types';
import { Route } from 'react-router-dom';
import Forbidden from '../../views/errors/Forbidden';
import { useAuth } from '../../contexts/AuthContext';
const ProtectedRoute = ({ roles, element, children, ...rest }) => {
const { user, login } = useAuth();
if (!user) {
login();
return <></>;
}
if (roles.length > 0) {
const routeRoles = roles.map((role) => role.toLowerCase());
const userRoles = (user && user.roles ? user.roles : []).map((role) => role.toLowerCase());
if (miscUtils.intersection(routeRoles, userRoles).length === 0) {
return <Forbidden />;
}
}
return (
<Route element={element} {...rest}>
{children}
</Route>
);
};
ProtectedRoute.propTypes = {
roles: PropTypes.arrayOf(PropTypes.string),
element: PropTypes.element,
children: PropTypes.node,
};
ProtectedRoute.defaultProps = {
roles: [],
element: null,
children: null,
};
export default ProtectedRoute;
Run Code Online (Sandbox Code Playgroud)
应用路由组件
import React from 'react';
import { Routes, Route, Navigate, Outlet } from 'react-router-dom';
import Login from './components/oauth/Login';
import Logout from './components/oauth/Logout';
import RenewToken from './components/oauth/RenewToken';
import ProtectedRoute from './components/ProtectedRoute';
import NotFound from './views/errors/NotFound';
import Index from './views/Index';
import MainContainer from './views/MainContainer';
import ViewUserProfile from './views/user/profile/ViewUserProfile';
import CreateUserProfile from './views/user/profile/CreateUserProfile';
import UpdateUserProfile from './views/user/profile/UpdateUserProfile';
import PartnerProfile from './views/partner/profile/PartnerProfile';
const AppRoutes = () => {
return (
<Routes>
{/* auth pages (important: do not place under /auth path) */}
<Route path="oauth/login" element={<Login />} />
<Route path="oauth/logout" element={<Logout />} />
<Route path="oauth/renew" element={<RenewToken />} />
<Route element={<MainContainer />}>
<Route path="/" element={<Index />} />
{/* protected routes */}
<ProtectedRoute path="user" element={<Outlet />}>
<Route path="/" element={<Navigate to="profile" replace />} />
<Route path="profile" element={<Outlet />}>
<Route path="/" element={<ViewUserProfile />} />
<Route path="create" element={<CreateUserProfile />} />
<Route path="update" element={<UpdateUserProfile />} />
</Route>
</ProtectedRoute>
<ProtectedRoute path="partner" roles={['partner']} element={<Outlet />}>
<Route path="/" element={<Navigate to="profile" replace />} />
<Route path="profile" element={<PartnerProfile />} />
</ProtectedRoute>
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
);
};
export default AppRoutes;
Run Code Online (Sandbox Code Playgroud)
您需要编写一个小包装器并使用Navigate组件进行重定向。您还需要渲染一条路线
const Container = ({Component, redirectLink, isAuthenticated, ...props}) => {
if(!isAuthenticated) {
return <Navigate to={redirectLink} />;
}
return <Component {...props} />
}
const PrivateRoute = ({ component: Component, redirectLink, isAuthenticated, path, ...props }) => {
return (
<Route
path={path}
element={<Container redirectLink={redirectLink} isAuthenticate={isAuthenticated} Component={Component} />}
/>
)
export default PrivateRoute;
Run Code Online (Sandbox Code Playgroud)
您可以在此处找到迁移指南the github docs
都是不错的选择。您还可以根据身份验证状态(或任何其他状态)简单地呈现不同的路由处理。您不必使用原始 Javascript 对象方法。
不要忘记您可以使用立即调用的匿名内部函数(() => COMPONENT)()来动态决定哪个组件处理特定的<Route/>.
这些示例可能尚未出现在初步文档中,v6因为处理 private<Route/>实际上非常简单。
例如
<Routes>
{state.authed ?
// Wait until we have the current user...
currentUser ?
<Route
path='/'
element={(() => {
// Show a "no access" message if the user is NOT an App Admin doesn't have access to any schools at all (which includes not having access to anything INSIDE any school either)
if (!currentUser.appAdministrator && currentUser.schoolIds?.length === 0) return <AdminNoAccess />
return <Outlet />
})()}
>
<Route
path='/'
element={(() => {
// If the user is a super user, we return the <SuperAdmin /> component, which renders some of its own routes/nav.
if (currentUser.appAdministrator) return <SuperAdmin />
return <Outlet />
})()}
>
<Route
path='schools'
element={(() => {
if (currentUser.schoolIds?.length === 1) {
return <Navigate to={`schools/schoolId`} />
} else {
return <AdminSchools />
}
})()}
/>
<Route path='users' children={<Users />} />
</Route>
<Route path={`schools/:schoolId`} element={<AdminSchool />} />
<Route path='*' element={<Navigate to='schools' />} />
</Route>
:
null
:
<>
<Route path='login' element={<Login />} />
<Route path='signup' element={<Signup />} />
<Route path='forgot-password' element={<ForgotPassword />} />
<Route path='reset-password' element={<ResetPassword />} />
<Route path='*' element={<Navigate to='login' />} />
</>
}
</Routes>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9971 次 |
| 最近记录: |