And*_*ski 2 javascript functional-programming reactjs higher-order-components react-router-v4
我有一个问题,以防止未经授权的用户访问授权的路由/组件 - 例如登录用户仪表板
我有以下代码:
import React from 'react'
//other imports
import {withRouter} from 'react-router'
class User extends React.Component {
constructor(props) {
super(props)
console.log('props', props)
let user = JSON.parse(localStorage.getItem('userDetails'))
if(!user || !user.user || props.match.params.steamId !== user.user.steamId) {
props.history.push('/')
} else {
this.props.updateUserState(user)
this.props.getUser(user.user.steamId)
}
}
//render function
}
//mapStateToProps and mapDispatchToProps
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(User))
Run Code Online (Sandbox Code Playgroud)
路由器:
render() {
return (
<Router>
<div>
<Route exact path="/" component={Main}/>
<Route path="/user/:steamId" component={User}/>
<Route path="/completelogin" component={CompleteLogin}/>
</div>
</Router>
)
}
Run Code Online (Sandbox Code Playgroud)
我尝试记录以检查是否输入了条件,但是我从渲染函数中得到一个错误,说它无法读取null的属性.
有没有办法解决我的问题,也有更好的方法来满足我的要求?只有授权用户才能严格访问特定组件
警告:以下答案使用React的旧上下文API.如果您使用的是V16.3 +,以下答案可能不适用于您
好的,根据您的逻辑,未经授权的用户被禁止访问用户组件.简单而公平.没问题.
但我担心的是你是否检查用户是否登录了未经身份验证的用户不应进入的组件.我认为这是不正确的,因为:
对我们的计划来说,这是一个额外的旅程 - 增加了额外的不必要的低效率.有可能从路由器我们转到用户组件,后者将我们发送回前者.乒乓.
用户组件看起来很脏.有无关的逻辑.是无关紧要的.因为不应在用户组件中进行身份验证检查.用户组件应包含用户相关的东西.
您认为如果不是进入用户组件来检查用户身份验证,我们会在路由器中检查这一点吗?用户组件,如其名称所描述的,专用于用户,并且应该从那里取出用于检查认证的逻辑.
好,这很酷.但是怎么样?
我们可以创建一个高阶组件(HOC)作为参数将任何组件传递给它.然后,我们在HOC中添加身份验证逻辑,最后,根据我们使用的逻辑,我们可以重定向到主页或允许对给定组件的请求.
为了使HOC能够执行上述操作,需要访问:
让我们说出HOC required_auth.这是它的代码:
import React, { Component } from 'react';
import { connect } from 'react-redux';
export default function(ComposedComponent) {
class Authentication extends Component {
static contextTypes = {
router: React.PropTypes.object
}
componentWillMount() {
if (!this.props.authenticated) {
this.context.router.history.push('/');
}
}
componentWillUpdate(nextProps) {
if (!nextProps.authenticated) {
this.context.router.history.push('/');
}
}
render() {
return <ComposedComponent {...this.props} />
}
}
function mapStateToProps(state) {
return { authenticated: state.auth.authed };
}
return connect(mapStateToProps)(Authentication);
}
Run Code Online (Sandbox Code Playgroud)
如你所见,这里没有黑魔法发生.可能令人困惑的是
static contextTypes = {
router: React.PropTypes.object
}
Run Code Online (Sandbox Code Playgroud)
context类似于props但它允许我们跳过组件层次结构中的级别
因为this.context非常容易访问和滥用,React强迫我们以这种方式定义上下文.
除非你真的知道自己在做什么,否则不要使用上下文.上下文的用例并不常见.了解更多关于什么样的后果可能是这里
总结一下我们的HOC,它只需要一个组件作为参数,它可以重定向到主页或返回我们将传递给它的组件.
现在使用它,在路径文件中我们导入HOC
import RequiredAuth from './components/auth/required_auth';
Run Code Online (Sandbox Code Playgroud)
以及我们想要保护免受非授权用户的任何路由,我们只需将其路由如下:
<Route path="/user" component={RequiredAuth(User)}/>
Run Code Online (Sandbox Code Playgroud)
上面的行将指向主页或返回我们正在传递的组件, User
参考文献:https : //facebook.github.io/react/docs/higher-order-components.html https://facebook.github.io/react/docs/context.html
由于您使用的是 React Router 4,Matthew Barbara 的答案虽然绝对正确,但不必要地复杂。使用 RR4,您可以简单地使用重定向组件来处理您的重定向。有关更多信息,请参阅https://reacttraining.com/react-router/web/api/Redirect。
import React, { Component } from "react";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";
export default function requireAuth (WrappedComponent) {
class Authentication extends Component {
render () {
if (!this.props.authenticated) {
return <Redirect to="/"/>
}
return <WrappedComponent { ...this.props }/>
}
}
function mapStateToProps (state) {
return { authenticated: state.authenticated }
}
return connect(mapStateToProps)(Authentication);
}
Run Code Online (Sandbox Code Playgroud)