PrivateRouter在React JS中无法正常运行

时间:2018-07-23 14:04:48

标签: javascript reactjs redux react-router react-redux

我正开始学习React JS。在我的项目中,我需要创建两条路由,一条用于用户身份验证,另一条需要重定向到登录页面。

我已经使用React Router创建了这个结构。这是路线的容器:

export const history = createHistory();

class AppContainer extends Component {

componentDidMount(){
    this.props.checkUserExist();
}


render() {

    return (
        <Router history={history}>
            <Switch>
                <PrivateRoute path="/" component={Welcome} exact={true}/>
                <PrivateRoute path="/friends"  component={Friends}/>
                <PublicRoute path="/login"  component={Login}/>
                <PrivateRoute path="/loves" component={Loves}/>
                <Route component={NotFoundPage}/>
            </Switch>
        </Router>
    );
}

}


  const mapDispatchToProps = (dispatch) => {
    return {    
     checkUserExist: () => dispatch(checkUser())     
    };
};

export default connect(undefined,mapDispatchToProps)(AppContainer);

这些是动作:

export const checkUser = () => (dispatch) => {

dispatch({
    type: CHECKING_USER,
    payload: {
       loading:true,
       isAuth:false
    }
});

from(axios.get('https://mysite.private.com/userExist', {
    withCredentials: true
})).subscribe((result) => {

    console.log('result:', result);

    result.data == null
        ? dispatch({
            type: USER_NOT_EXIST,
            payload: {
                isAuth: false,
                loading:false
            }
        })

        : dispatch({
            type: USER_EXIST,
            payload: {
                isAuth: true,
                user:result.data,
                loading: false
            }
        });

}, (error) => dispatch({
    type: USER_CHECKING_ERROR,
    payload: {
        loading: false,
        isAuth:false,
        error
    }
 }));
};

和减速器:

const user = (state = {}, action) => {

switch (action.type) {

    case CHECKING_USER:

        return{
            ...state,
            ...action.payload
        };

    case USER_EXIST:

        return {
            ...state,
            ...action.payload
        };
    case USER_NOT_EXIST:

        return {
            ...state,
            ...action.payload
        };

    case USER_CHECKING_ERROR:
        return {
            ...state,
            ...action.payload
        }


    default:
        return state;
 }
};

export default user;

在Redux中。

最后,这是PrivateRoute的声明:

import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';


export const PrivateRoute = ({
     isAuthenticated, 
     component: Component, 
     ...rest 
    }) => (

    <Route {...rest} component={(props) => (
        isAuthenticated ? (
            <div><Component {...props} /></div>
        ) : (
            <Redirect to="/login" />
        )
    )}/>

);

const mapStateToProps = (state) => ({
    isAuthenticated: state.user.isAuth
});


export default connect (mapStateToProps)(PrivateRoute);

PublicRoute

import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';


export const PublicRoute = ({
     isAuthenticated, 
     component: Component, 
     ...rest 
    }) => (

    <Route {...rest} component={(props) => (
        isAuthenticated ? (
            <Redirect to="/" />
        ) : (
            <Component {...props} />
        )
    )}/>

);

const mapStateToProps = (state) => ({
    isAuthenticated: state.user.isAuth
});


export default connect (mapStateToProps)(PublicRoute);

错误是这样的:例如,在加载'/friends'时,它先加载到Login组件,然后再加载到'/',然后加载到Welcome组件中。这可能是因为它在checkUserExist()完成之前渲染。

我的问题是:有办法避免吗?也许使用超时或等待ajax调用完成。

谢谢您的回答。

1 个答案:

答案 0 :(得分:0)

import React from 'react';
import { connect } from 'react-redux';
import { Route, Redirect } from 'react-router-dom';


export const PublicRoute = ({
     isAuthenticated, 
     component: Component, 
     ...rest 
    }) => {

    isAuthenticated ? localStorage.setItem("red", "") : localStorage.setItem(history.location.pathname) ;
    return (<Route {...rest} component={(props) => (
        isAuthenticated ? (
            <Redirect to="/" />
        ) : (
            <Component {...props} />
        )
    )}/>);

};

const mapStateToProps = (state) => ({
    isAuthenticated: state.user.isAuth
});


export default connect (mapStateToProps)(PublicRoute);


export const history = createHistory();

class AppContainer extends Component {

componentDidMount(){
    this.props.checkUserExist();
}

redirectMe = () => {
    const redirect= localStorage.getItem("red");
    localStorage.getItem("red", "");
    if(redirect !== "")
        return <Redirect to={redirect} />
}

render() {
    redirectMe()
    return (
        <Router history={history}>
            <Switch>
                <PrivateRoute path="/" component={Welcome} exact={true}/>
                <PrivateRoute path="/friends"  component={Friends}/>
                <PublicRoute path="/login"  component={Login}/>
                <PrivateRoute path="/loves" component={Loves}/>
                <Route component={NotFoundPage}/>
            </Switch>
        </Router>
    );
}

}


  const mapDispatchToProps = (dispatch) => {
    return {    
     checkUserExist: () => dispatch(checkUser())     
    };
};

export default connect(undefined,mapDispatchToProps)(AppContainer);

我做了什么?

我在私有路由中添加了一个条件,即如果用户未通过身份验证并且正在寻找私有路由,则被调用的url将存储在本地存储中。

由于AppRouter每次都会渲染,因此它将检查是否找到了任何URL的本地存储,它将移动到该URL并清除本地存储。

注意:如果这不起作用,则在状态中创建一个变量,然后在AppRouter.js中连接该状态变量,而不是在该位置中设置为localstorage set状态。