2017-10-19 39 views
0

我正在使用HOC组件来限制对未登录用户的路由访问。这个HOC重新挂载子组件时挂载或重新呈现时,直接从url访问此路线(在应用程序第一次加载时)的问题。例如,我在PaperWorkProgress组件中有3次did mount路由授权HOC导致重新安装儿童3次

路由定义:

<Route path="/paperwork/progress" component={RequireAuth(PaperWorkProgress)}/> 

这里HOC代码:

import React, {Component} from 'react'; 
import {connect} from 'react-redux'; 

export default function(ComposedComponent) { 
    class Authentication extends Component { 

    // check if token exists in storage 
    componentWillMount() { 
     const token = localStorage.getItem('token'); 
     if (!token) { 
     const {pathname, search} = this.props.location; 
     this.props.history.push({ 
      pathname: '/signin', 
      search: `?redirect_to=${pathname}${search}`, 
     }); 
     } 
    } 

    // additional check 
    componentWillUpdate(nextProps) { 
     if (!nextProps.loggedIn) { 
     const {pathname, search} = this.props.location; 
     this.props.history.push({ 
      pathname: '/signin', 
      search: `?redirect_to=${pathname}${search}`, 
     }); 
     } 
    } 

    render() { 
     return <ComposedComponent {...this.props} />; 
    } 
    } 

    function mapStateToProps(state) { 
    return {loggedIn: state.session.loggedIn}; 
    } 

    return connect(mapStateToProps)(Authentication); 
} 

任何想法?

+0

尝试把它'componentDidMount' – Dane

+0

我在细节上如何一个auth HOC可以用在刀刃上解释这里:https://stackoverflow.com/questions/46379934/react-router-v4-authorized-routes-and-components –

+0

@MatthewBarbara我的HOC基于你的解决方案,但没有上下文功能。 – Kort

回答

0

我不确定这会对重新渲染问题产生影响,但是您的代码感觉不对。

首先,你似乎有2个真相源,你的redux商店和localStorage,这使事情变得复杂。如果您想从之前的导航信息中“保存”商店,则应使用createStore“preloadedState”参数,而不是每次都在组件中进行检查。 Cf Redux doc和Redux自己的创作者的视频Video for persisting and rehydrating State。一旦你的状态只来自你的商店,它开始变得更加简单。

其次,

当你推到组件里面的历史记录对象,感觉就像你是变异的组件自己的道具(如历史是一个道具)。这对我来说很奇怪,可能是你问题的根源。

为什么不使用像这样的渲染方法中的重定向组件? cf React router docs。组件将看起来像这样(很明显,你需要在文档中改变你的登录组件太像)

import React, { Component } from "react"; 
import { connect } from "react-redux"; 
import { Redirect } from "react-router-dom"; 

export default function(ComposedComponent) { 
    class Authentication extends Component { 
    render() { 
     return !this.props.loggedIn ? (
     <Redirect 
      to={{ 
      pathname: "/login", 
      state: { from: this.props.location } 
      }} 
      {...this.props} 
     /> 
    ) : (
     <ComposedComponent {...this.props} /> 
    ); 
    } 
    } 

    function mapStateToProps(state, ownProps) { 
    return { loggedIn: state.session.loggedIn, ...ownProps }; 
    } 
    return connect(mapStateToProps)(Authentication); 
} 
+0

我使用的是localStorage,因为在应用程序中第一次加载'state.session.loggedIn'仍然不存在并且只在'refresh token'动作后填充,并且它总是进行重定向。 – Kort