React-Redux how to prevent page from rendering before redirect

若如初见. 提交于 2020-03-01 03:44:26

问题


I'm working on a personal project and I have trouble with checking if a user is logged in or not so that when they try to go to /login, it'll redirect them to the home page. Currently what my code does is the following:

  1. Defined my own Route components
  2. When checkIfSignedIn is called, it dispatches actions that set the isLoggedIn state to either True or False.
  3. The AuthenticatedRouter component checks if the store's isLoggedIn state is true or false and will either render the component or redirect to home.
  4. This works, but the issue is that isLoggedIn is initially false, so if they are logged in, the login form shows up for a second and then redirects after isLoggedIn becomes true.

I can't figure out how to fix the problem with rendering the component with the default state and then suddenly redirects because the state changes. Thanks

  • I'm using firebase for the user account.

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 - action creators

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 solution (Not sure if this is frowned upon).

I set my Auth reducer's default state, isLoggedIn : null instead of false. Then in my AuthorizedRoute component I now have 3 conditions to render null first and then either the component or redirect.

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

回答1:


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);



回答2:


What you may do is something like this: (in your auth reducer).

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

Also you had to set the localstorage when your user is logging in and remove it when he is logging out.



来源:https://stackoverflow.com/questions/47901695/react-redux-how-to-prevent-page-from-rendering-before-redirect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!