【问题标题】:React-Redux how to prevent page from rendering before redirectReact-Redux 如何防止页面在重定向之前呈现
【发布时间】:2017-12-20 08:27:51
【问题描述】:

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

  1. 定义了我自己的 Route 组件
  2. 调用 checkIfSignedIn 时,它会调度将 isLoggedIn 状态设置为 True 或 False 的操作。
  3. AuthenticatedRouter 组件检查商店的 isLoggedIn 状态是 true 还是 false,并将呈现组件或重定向到主页。
  4. 这可行,但问题是 isLoggedIn 最初为 false,因此如果他们已登录,登录表单会显示一秒钟,然后在 isLoggedIn 变为 true 后重定向。

我不知道如何解决以默认状态渲染组件然后由于状态更改而突然重定向的问题。谢谢

  • 我正在为用户帐户使用 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 - 减速器

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

【问题讨论】:

标签: reactjs redux react-router react-redux


【解决方案1】:

你可以做的是这样的事情:(在你的 auth reducer 中)。

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

您还必须在用户登录时设置本地存储,并在用户注销时将其删除。

【讨论】:

  • 这可行。我担心的一件事是不需要我更改大部分操作,因为我目前正在使用 Firebase 的 firebaseApp.auth().onAuthStateChanged 来检查用户是否登录。
  • 如何在您的操作中添加 localStorage(类似这样) firebaseApp.auth().onAuthStateChanged(user => { if (user){ dispatch(setSignedInTrue()); localStorage.setItem(' user', JSON.stringify({user: user})); } else{ dispatch(setSignedInFalse()); localStorage.removeItem('user'); } });
  • 谢谢,我会调查的。您能否也看看我上面编辑的解决方案并告诉我您的想法?再次感谢
  • 好吧,没有“糟糕的解决方案”,但是如果您的连接有问题,这个应该会很奇怪,或者稍后应用程序会缓慢呈现,因此 null 返回将是“可见的”你可能不喜欢这样(可能是我现在没有考虑的其他问题)
  • 这节省了我在谷歌上搜索的时间!谢谢@FabienGreard
【解决方案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);

【讨论】:

  • 如果我要使用这个解决方案,因为我会将用户登录信息存储在 localStorage 中并进行检查,所以我不需要为 AuthorizedRoute 使用 redux 状态对吗?
  • 是的,你不需要 redux 状态。
猜你喜欢
  • 1970-01-01
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多