React-Redux如何在重定向之前阻止页面呈现

时间:2017-12-20 08:27:51

标签: reactjs redux react-router react-redux

我正在处理个人项目,但我无法检查用户是否已登录,因此当他们尝试进入/登录时,会将其重定向到主页。目前我的代码的作用如下:

  1. 定义了我自己的路线组件
  2. 调用checkIfSignedIn时,会调度将isLoggedIn状态设置为True或False的操作。
  3. AuthenticatedRouter组件检查商店的isLoggedIn状态是true还是false,并将呈现组件或重定向到home。
  4. 这样可行,但问题是isLoggedIn最初为false,因此如果他们已登录,登录表单会显示一秒钟,然后在isLoggedIn变为true后重定向。
  5. 我无法弄清楚如何通过使用默认状态渲染组件来解决问题,然后突然重定向,因为状态发生了变化。感谢

    • 我使用firebase作为用户帐户。

    Routes.js

    const Routes = (props) => {
        props.checkIfSignedIn();
        return(
            <Router>
                <Switch>
                    <Route exact path='/' component={App}/>
                    <AuthorizedRoute path="/signup" component={SignUp}/>
                    <AuthorizedRoute path="/signin" component={SignIn}/>
                    <Route component={InvalidPage}/>
                </Switch>
            </Router>
        );
    };
    
    const mapDispatchToProps = (dispatch) => {
        return{
            checkIfSignedIn: () => dispatch(checkIfSignedIn())
        };
    };
    
    export default connect(null, mapDispatchToProps)(Routes);
    

    AuthorizedRoute.js

    class AuthorizedRoute extends React.Component{
        constructor(props){
            super(props);
            this.state = {
                isLoggedIn: false
            };
        };
    
        render(){
            const { component: Component, ...rest } = this.props;
            return(
                <Route {...rest} render={props => {
                    if (this.props.isLoggedIn){
                        console.log(this.state.isLoggedIn);
                        return <Redirect to="/" />
                    } else{
                        return <Component {...props} />
                    }
                }} />
            );
        }
    };
    
    
    const mapStateToProps = (state) => {
        return{
            isLoggedIn : state.authentication.isLoggedIn
        };
    };
    
    export default connect(mapStateToProps, null)(AuthorizedRoute);
    

    authentication.js - 动作创建者

    const setSignedInFalse = () => {
        return{
            type: IS_SIGNED_IN_FALSE
        };
    };
    
    const setSignedInTrue = () => {
        return{
            type: IS_SIGNED_IN_TRUE
        };
    };
    
    const checkIfSignedIn = () => {
        return dispatch => {
            firebaseApp.auth().onAuthStateChanged(user => {
                if (user){
                    dispatch(setSignedInTrue());
                } else{
                    dispatch(setSignedInFalse());
                }
            });
        };
    };
    
    export default checkIfSignedIn;
    

    authentication.js - reducer

    const defaultState = {
        isLoggedIn: false
    };
    
    const authentication = (state = defaultState, action) => {
        let authenticationState = null;
        switch (action.type){
            case IS_SIGNED_IN_FALSE:
                authenticationState = {
                    isLoggedIn: false
                };
                return authenticationState;
            case IS_SIGNED_IN_TRUE:
                authenticationState = {
                    isLoggedIn: true
                };
                return authenticationState;
            default:
                return state;
        };
    };
    
    export default authentication;
    

    Hacky解决方案(不确定这是否令人不满)。

    我设置了Auth reducer的默认状态,isLoggedIn:null而不是false。然后在我的AuthorizedRoute组件中,我现在有3个条件首先渲染null,然后是组件或重定向。

    //AuthorizedRoute Component
    if (this.props.isLoggedIn){
        return <Redirect to="/" />
    } else if (this.props.isLoggedIn === false){
        return <Component {...props} />
    } else{
        return null;
    }
    

2 个答案:

答案 0 :(得分:2)

class AuthorizedRoute extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isLoggedIn: false
        };
    };

    render() {
        const { component: Component, ...rest } = this.props;
        const user = JSON.parse(localStorage.getItem('user'));
        return (
            <Route { ...rest } render={ props => user ? <Component {...props} /> : <App /> } />
        );
    }
};


const mapStateToProps = (state) => {
    return {
        isLoggedIn : state.authentication.isLoggedIn
    };
};

export default connect(mapStateToProps, null)(AuthorizedRoute);

答案 1 :(得分:1)

你可能做的是这样的:(在你的auth reducer中)。

let user = JSON.parse(localStorage.getItem('user'));
const initialState = user ? { isLoggedIn: true } : {};

此外,您必须在用户登录时设置localstorage,并在注销时将其删除。