Jie*_*eng 100 javascript reactjs react-router react-router-v4
我试图实现经过身份验证的路由,但发现React Router 4现在阻止了它的工作:
<Route exact path="/" component={Index} />
<Route path="/auth" component={UnauthenticatedWrapper}>
<Route path="/auth/login" component={LoginBotBot} />
</Route>
<Route path="/domains" component={AuthenticatedWrapper}>
<Route exact path="/domains" component={DomainsIndex} />
</Route>
Run Code Online (Sandbox Code Playgroud)
错误是:
警告:您不应该使用
<Route component>和使用<Route children>相同的路线;<Route children>将被忽略
在这种情况下,有什么正确的方法来实现这个?
它出现在react-router(v4)docs中,它表明了类似的东西
<Router>
<div>
<AuthButton/>
<ul>
<li><Link to="/public">Public Page</Link></li>
<li><Link to="/protected">Protected Page</Link></li>
</ul>
<Route path="/public" component={Public}/>
<Route path="/login" component={Login}/>
<PrivateRoute path="/protected" component={Protected}/>
</div>
</Router>
Run Code Online (Sandbox Code Playgroud)
但是,将一堆路线组合在一起是否有可能实现这一目标?
UPDATE
好的,经过一些研究,我想出了这个:
import React, {PropTypes} from "react"
import {Route} from "react-router-dom"
export default class AuthenticatedRoute extends React.Component {
render() {
if (!this.props.isLoggedIn) {
this.props.redirectToLogin()
return null
}
return <Route {...this.props} />
}
}
AuthenticatedRoute.propTypes = {
isLoggedIn: PropTypes.bool.isRequired,
component: PropTypes.element,
redirectToLogin: PropTypes.func.isRequired
}
Run Code Online (Sandbox Code Playgroud)
如果发送动作是正确的,render()那就错了.它componentDidMount或其他钩子看起来不是很正确吗?
Tyl*_*nis 197
您将要使用该Redirect组件.这个问题有几种不同的方法.这是我喜欢的一个,有一个PrivateRoute组件,它接受authed道具,然后根据道具渲染.
function PrivateRoute ({component: Component, authed, ...rest}) {
return (
<Route
{...rest}
render={(props) => authed === true
? <Component {...props} />
: <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
/>
)
}
Run Code Online (Sandbox Code Playgroud)
现在你的Routes看起来像这样
<Route path='/' exact component={Home} />
<Route path='/login' component={Login} />
<Route path='/register' component={Register} />
<PrivateRoute authed={this.state.authed} path='/dashboard' component={Dashboard} />
Run Code Online (Sandbox Code Playgroud)
如果您仍然感到困惑,我写了这篇可能有帮助的帖子 - 使用React Router v4保护路由和身份验证
fer*_*mmm 38
根据react-router-dom文档,到2022年,render该组件的属性Route将用于遗留用途,甚至在V5中不再工作,并且在V6中被删除。
这有效:
const RequireAuth: FC<{ children: React.ReactElement }> = ({ children }) => {
const userIsLogged = useLoginStatus(); // Your hook to get login status
if (!userIsLogged) {
return <LoginPage />;
}
return children;
};
Run Code Online (Sandbox Code Playgroud)
用法:
/* A route that doesn't require login */
<Route
path="sign-up"
element={
<SignUpPage />
}
/>
/* A route that requires login */
<Route
path="dashboard"
element={
<RequireAuth>
<DashboardPage />
</RequireAuth>
}
/>
Run Code Online (Sandbox Code Playgroud)
编辑: 我将代码示例更新为 React Router v6
MrD*_*uDu 15
Tnx Tyler McGinnis寻求解决方案.我从Tyler McGinnis的想法中提出我的想法.
const DecisionRoute = ({ trueComponent, falseComponent, decisionFunc, ...rest }) => {
return (
<Route
{...rest}
render={
decisionFunc()
? trueComponent
: falseComponent
}
/>
)
}
Run Code Online (Sandbox Code Playgroud)
你可以这样实现
<DecisionRoute path="/signin" exact={true}
trueComponent={redirectStart}
falseComponent={SignInPage}
decisionFunc={isAuth}
/>
Run Code Online (Sandbox Code Playgroud)
decisionFunc只是一个返回true或false的函数
const redirectStart = props => <Redirect to="/orders" />
Run Code Online (Sandbox Code Playgroud)
Hem*_*vrm 11
(使用 Redux 进行状态管理)
如果用户尝试访问任何 url,首先我将检查访问令牌是否可用,如果没有重定向到登录页面,一旦用户使用登录页面登录,我们会将其存储在 localstorage 以及我们的 redux 状态中。(localstorage 或 cookies ..我们暂时将这个主题与上下文无关)。
因为 redux 状态已更新,privateroutes 将被重新渲染。现在我们有了访问令牌,所以我们要重定向到主页。
将解码的授权有效负载数据也存储在 redux 状态并将其传递给 react 上下文。(我们不必使用上下文,而是在任何嵌套的子组件中访问授权,这使得从上下文访问变得容易,而不是将每个子组件连接到 redux)。
所有不需要特殊角色的路由都可以在登录后直接访问..如果它需要像admin这样的角色(我们做了一个受保护的路由,如果没有重定向到未经授权的组件,它会检查他是否有想要的角色)
如果您必须根据角色禁用按钮或其他内容,则在您的任何组件中类似。
只是你可以这样做
const authorization = useContext(AuthContext);
const [hasAdminRole] = checkAuth({authorization, roleType:"admin"});
const [hasLeadRole] = checkAuth({authorization, roleType:"lead"});
<Button disable={!hasAdminRole} />Admin can access</Button>
<Button disable={!hasLeadRole || !hasAdminRole} />admin or lead can access</Button>
Run Code Online (Sandbox Code Playgroud)
那么如果用户尝试在 localstorage 中插入虚拟令牌怎么办。由于我们有访问令牌,我们将重定向到 home 组件。我的 home 组件将进行 rest 调用以获取数据,因为 jwt 令牌是虚拟的,rest 调用将返回未经授权的用户。所以我确实调用了注销(这将清除本地存储并再次重定向到登录页面)。如果主页有静态数据并且没有进行任何 api 调用(那么您应该在后端进行令牌验证 api 调用,以便您可以在加载主页之前检查令牌是否为 REAL)
索引.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, Switch } from 'react-router-dom';
import history from './utils/history';
import Store from './statemanagement/store/configureStore';
import Privateroutes from './Privateroutes';
import Logout from './components/auth/Logout';
ReactDOM.render(
<Store>
<Router history={history}>
<Switch>
<Route path="/logout" exact component={Logout} />
<Route path="/" exact component={Privateroutes} />
<Route path="/:someParam" component={Privateroutes} />
</Switch>
</Router>
</Store>,
document.querySelector('#root')
);
Run Code Online (Sandbox Code Playgroud)
历史.js
import { createBrowserHistory as history } from 'history';
export default history({});
Run Code Online (Sandbox Code Playgroud)
私有路由.js
import React, { Fragment, useContext } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { AuthContext, checkAuth } from './checkAuth';
import App from './components/App';
import Home from './components/home';
import Admin from './components/admin';
import Login from './components/auth/Login';
import Unauthorized from './components/Unauthorized ';
import Notfound from './components/404';
const ProtectedRoute = ({ component: Component, roleType, ...rest })=> {
const authorization = useContext(AuthContext);
const [hasRequiredRole] = checkAuth({authorization, roleType});
return (
<Route
{...rest}
render={props => hasRequiredRole ?
<Component {...props} /> :
<Unauthorized {...props} /> }
/>)};
const Privateroutes = props => {
const { accessToken, authorization } = props.authData;
if (accessToken) {
return (
<Fragment>
<AuthContext.Provider value={authorization}>
<App>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" render={() => <Redirect to="/" />} />
<Route exact path="/home" component={Home} />
<ProtectedRoute
exact
path="/admin"
component={Admin}
roleType="admin"
/>
<Route path="/404" component={Notfound} />
<Route path="*" render={() => <Redirect to="/404" />} />
</Switch>
</App>
</AuthContext.Provider>
</Fragment>
);
} else {
return (
<Fragment>
<Route exact path="/login" component={Login} />
<Route exact path="*" render={() => <Redirect to="/login" />} />
</Fragment>
);
}
};
// my user reducer sample
// const accessToken = localStorage.getItem('token')
// ? JSON.parse(localStorage.getItem('token')).accessToken
// : false;
// const initialState = {
// accessToken: accessToken ? accessToken : null,
// authorization: accessToken
// ? jwtDecode(JSON.parse(localStorage.getItem('token')).accessToken)
// .authorization
// : null
// };
// export default function(state = initialState, action) {
// switch (action.type) {
// case actionTypes.FETCH_LOGIN_SUCCESS:
// let token = {
// accessToken: action.payload.token
// };
// localStorage.setItem('token', JSON.stringify(token))
// return {
// ...state,
// accessToken: action.payload.token,
// authorization: jwtDecode(action.payload.token).authorization
// };
// default:
// return state;
// }
// }
const mapStateToProps = state => {
const { authData } = state.user;
return {
authData: authData
};
};
export default connect(mapStateToProps)(Privateroutes);
Run Code Online (Sandbox Code Playgroud)
checkAuth.js
import React from 'react';
export const AuthContext = React.createContext();
export const checkAuth = ({ authorization, roleType }) => {
let hasRequiredRole = false;
if (authorization.roles ) {
let roles = authorization.roles.map(item =>
item.toLowerCase()
);
hasRequiredRole = roles.includes(roleType);
}
return [hasRequiredRole];
};
Run Code Online (Sandbox Code Playgroud)
解码的 JWT 代币样本
{
"authorization": {
"roles": [
"admin",
"operator"
]
},
"exp": 1591733170,
"user_id": 1,
"orig_iat": 1591646770,
"email": "hemanthvrm@stackoverflow",
"username": "hemanthvrm"
}
Run Code Online (Sandbox Code Playgroud)
const Root = ({ session }) => {
const isLoggedIn = session && session.getCurrentUser
return (
<Router>
{!isLoggedIn ? (
<Switch>
<Route path="/signin" component={<Signin />} />
<Redirect to="/signin" />
</Switch>
) : (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
<Route path="/something-else" component={SomethingElse} />
<Redirect to="/" />
</Switch>
)}
</Router>
)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
80829 次 |
| 最近记录: |