React-Route 4.0 实现一个简单的路由登录拦截

发布于 2022-09-05 15:48:05 字数 1669 浏览 9 评论 0

React-Route 4.0 舍去了路由钩子
为了实现在需要登录才能进入某个路由,说白了就是前端路由拦截
看例子实现的好像有点乱,自己这样实现了一下,不知道可以不可以,功能可以的

    /*
* 登录验证
* */
import React from 'react';
import Login from '../pages/login'
import {Route} from 'react-router-dom'

const isEmptyChildren = (children) =>
React.Children.count(children) === 0

class AuthRoute extends Route {
  render() {
    //完全覆盖父类方法
    const { match } = this.state
    const { children, component, render } = this.props
    const { history, route, staticContext } = this.context.router
    const location = this.props.location || route.location
    const props = { match, location, history, staticContext }
    if (component){
        if(!match) return null;
        return  this.state.isAuthed ? React.createElement(component, props) : React.createElement(Login, props)
    }
    if (render)
        return match ? render(props) : null

    if (typeof children === 'function')
        return children(props)

    if (children && !isEmptyChildren(children))
        return React.Children.only(children)
    return null
}
componentWillMount(){
    //重写父类方法
    super.componentWillMount();
    const { match } = this.state;
    if(match){
        console.log('componentWillMount()')
        this.auth();
    }
}
componentWillReceiveProps(nextProps,nextContext){
    //重写父类方法
    super.componentWillReceiveProps(nextProps,nextContext);
            const { match } = this.props;
           if(match ){
                console.log('componentWillReceiveProps')
       this.auth();
           }
}
auth(){
    setTimeout(()=>{
        this.setState({isAuthed:true})
    },2000)
  }
}
export default AuthRoute

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不知所踪 2022-09-12 15:48:05

楼主的这种实现复杂化了,官网的那个例子不是很简洁吗,在Route的render方法内做认证判断,从而决定是否渲染组件还是重定向到登录路由,不需要重写Route的原有方法。


const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>
    )
  )}/>
)

以下是更新:

const PrivateRoute = ({ component: Component, ...rest }) => (
  return class extends Component {
    constructor(props){
      super(props);
      this.state = {
        auth : false,     // 表示是否认证通过
        hasAuthed: false,  // 表示是否向服务器发送过认证请求
      };
    }
    
    componentDidMount() {
       //authPromise 向服务器发送认证请求,示例以Promise形式返回,result表示认证是否成功
       authPromise().then(result => { 
         if(result == true) {
           this.setState({auth:true, hasAuthed: true});
         }else {
           this.setState({auth:false, hasAuthed: true});
         }
      })
    }
    
    render() {
      // 初始渲染时,尚未向服务器发送认证请求,因此不渲染元素
      if(!this.state.hasAuthed){
        return null;
      }
       <Route {...rest} render={props => (
        this.state.auth ? (
          <Component {...props}/>
        ) : (
          <Redirect to={{
            pathname: '/login',
            state: { from: props.location }
          }}/>
        )
      )}/>
     }
  }
)
猛虎独行 2022-09-12 15:48:05

@艾特老干部 老哥,按照你的监听路由的方式我试了下,好像只能用push,replace之类的方法才能重渲染,而如果是go(-1)的方式登录验证完回到之前的页面则不会走render的逻辑,请问这种情况咋办呢

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文