Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React路由器v4-使用HOC的授权路由_Javascript_Reactjs_Functional Programming_React Router V4_Higher Order Components - Fatal编程技术网

Javascript React路由器v4-使用HOC的授权路由

Javascript React路由器v4-使用HOC的授权路由,javascript,reactjs,functional-programming,react-router-v4,higher-order-components,Javascript,Reactjs,Functional Programming,React Router V4,Higher Order Components,我遇到了一个问题,无法阻止未经授权的用户访问仅授权的路由/组件,例如登录用户仪表板 我有以下代码: 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

我遇到了一个问题,无法阻止未经授权的用户访问仅授权的路由/组件,例如登录用户仪表板

我有以下代码:

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))
路由器:

render() {
    return (
      <Router>
        <div>
          <Route exact path="/" component={Main}/>
          <Route path="/user/:steamId" component={User}/>
          <Route path="/completelogin" component={CompleteLogin}/>
        </div>
      </Router>
    )
  }
render(){
返回(
)
}
我尝试记录日志来检查是否输入了条件,但是我从render函数得到一个错误,说它无法读取null的属性


有没有办法解决我的问题,也有更好的方法来满足我的需求?只有授权用户才能严格访问特定组件警告:以下答案使用React的旧上下文API。如果您使用的是V16.3+,以下答案不适用于您

好的,根据您的逻辑,未经授权的用户被禁止访问用户组件。简单而公平。没问题

但我担心的是,您是否正在检查用户是否登录到未经身份验证的用户不应进入的组件中。我认为这是不正确的,因为:

  • 这对我们的计划来说是一个额外的旅程——额外增加了一点不必要的低效。有一种可能性,我们从路由器转到用户组件,后者将我们送回前者。乒乓球

  • 用户组件看起来脏了。有不相关的逻辑。是的,不相关。因为不应在用户组件中执行身份验证检查。用户组件应该包含与用户相关的内容

  • 如果我们不进入用户组件检查用户身份验证,而是在路由器中检查它,您会怎么想?顾名思义,用户组件是专用于用户的,检查身份验证的逻辑应该从中删除

    好的,很酷。但是怎么做呢?

    我们可以创建一个参数,它将接受传递给它的任何组件。然后,我们在HOC中添加身份验证逻辑,最后,根据我们使用的逻辑,我们可以重定向到主页或允许请求到给定组件

    为了使HOC能够执行上述操作,它需要访问:

  • 国家。我们需要知道用户是否已登录,以及存储此类数据的状态
  • 路由器。我们可能需要重定向用户
  • 让我们命名HOC
    required\u 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);
    }
    
    context
    类似于
    props
    ,但它允许我们跳过 组件层次结构中的级别

    因为
    this.context
    非常容易访问和滥用,迫使我们以这种方式定义上下文

    除非你真的知道自己在做什么,否则不要使用上下文。上下文的用例并不常见。阅读更多有关后果的信息

    最后,在我们的HOC中,它只是将一个组件作为参数,它要么重定向到主页,要么返回我们将传递给它的组件

    现在要使用它,我们在路由文件中导入HOC

     import RequiredAuth from './components/auth/required_auth';
    
    我们想要保护未经授权的用户的任何路由,我们只需按如下方式路由:

    <Route path="/user" component={RequiredAuth(User)}/>
    
    
    
    上面的行将指向主页或返回我们正在传递的组件,
    User

    参考资料:

    由于您使用的是React Router 4,Matthew Barbara的答案虽然绝对正确,但却不必要地复杂。使用RR4,您可以简单地使用重定向组件来处理重定向。有关更多信息,请参阅

    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);
    }
    
    import React,{Component}来自“React”;
    从“react redux”导入{connect};
    从“react router dom”导入{Redirect};
    导出默认函数requireAuth(WrappedComponent){
    类身份验证扩展了组件{
    渲染(){
    如果(!this.props.authenticated){
    返回
    }
    返回
    }
    }
    函数MapStateTops(状态){
    返回{authenticated:state.authenticated}
    }
    返回连接(MapStateTops)(身份验证);
    }
    
    理想情况下,您应该将身份验证变量设置为false,然后在componentWillMount或componentDidMount中检查条件,而不是在构造函数中检查条件,正如@Shubham Khatri所说,您不应该在构造函数中放入任何逻辑,而是使用生命周期方法。另外,要小心,您在同一个方法中同时使用了
    props
    this.props
    。@ShubhamKhatri谢谢,添加到componentWillMount时它起作用了。我还不熟悉如何应对和了解组件的生命周期。你能展示一下路由器的代码吗?其中配置了实际路由。通常它位于main/app/index文件中。“我怀疑问题是从那里来的。@MatthewBarbara我已经在我的问题中添加了路由器的代码。路由器是浏览器路由器。另外,当我在render方法中呈现常规HTML时,将逻辑添加到ComponentMount会起作用,当我将自定义组件添加到用户组件时,它会再次失败。我是否遗漏了什么。。。当没有人发送道具时,这个HOC怎么会收到道具呢?如何获得
    此.props.authenticated
    ?mapStateToProps函数正在实现这一点我已经找到了与您相同的解决方案,关于如何使用Jest&Ezyme测试此HOC,有什么提示吗?
    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);
    }