受保护的路由器在 Redux 状态更新时不会重新渲染

Protected router doesn't re-render when Redux state update

我正在尝试使用受保护的路由来防止未经身份验证的用户看到页面。为此,每次重新加载页面时,我都会连接到服务器以检查令牌并查看用户是否已通过身份验证,并根据服务器响应更新 Redux 状态。这工作正常,但是当我尝试更新受保护的路由组件时出现问题。由于服务器响应延迟,组件第一次渲染默认状态值为 false,但是当我获得服务器响应并将 Redux 状态更新为 true 时,我的组件不会重新渲染 [=13] =]

function ProtectedRoute(props, {component: Component, ...rest}){
    return (
        <Route 
            {...rest}
            render={props =>{
               if(props.userLoginStatus){
                    console.log('protected if')
                    return <Component {...props} />
                } else {
                    console.log('protected else')
                    return <Redirect to={{
                        pathname: '/forbidden',
                        state: {from: props.location}
                    }}
                    />
                }
            }}
        />
    )
}

const mapStateToProps = (state) => {
    return {
        userLoginStatus: state.userLoginReducer.userLogin
    }
}

export default connect(mapStateToProps)(ProtectedRoute)

也许您可以使用如下所示的“browserHistory”进行重定向。

import { browserHistory } from 'react-router'

// ...
else {
       console.log('protected else')
       return browserHistory.push('/forbidden');
     }

我也有类似的问题。

首先,您需要派发一个操作来检查用户是否在您的商店呈现后立即通过身份验证。

由于身份验证似乎是一个异步过程,您可能希望发送两个操作:auth_verification_request 商店首次呈现时,以及 auth_verification_success 身份验证成功时。

然后更新的状态将使用 mapStateToProps 函数发送到您的 ProtectedRoute。之后,您的组件应该 re-render 在身份验证状态更新后。

我给你举几个例子。

authActions.js

export const verifyAuth = () => {
        return ((dispatch) => {

            // auth verification requested
            dispatch({
                   type: 'VERIFY_REQUEST'
            })

            // signin request
            dispatch({
                    type: 'SIGN_IN_REQUEST'
            });

            // check if user is logged in or not
            if (logged_in) {

                // signin success
                dispatch({
                        type: 'SIGN_IN_SUCCESS'
                
                })

                // auth verification success
                dispatch({
                        type: 'VERIFY_SUCCESS'
                })
            }

            // if not logged in
            else {
                
                // auth verification rejected
                dispatch({
                        type: 'VERIFY_ERROR'
                })
            }
        }
    }

你的 ProtectedRoute 应该看起来像这样:

ProtectedRoute.js

const ProtectedRoute = ({
    component: Component,
    isAuthenticated,
    isVerifying,
    ...rest
}) => {

    return (
        <Route { ...rest }
            render={ props =>

                isVerifying ? (
                    <div />
                ) : isAuthenticated ? (
                    <Component { ...props } />
                ) : (
                            <Redirect
                                to={ {
                                    pathname: 'REDIRECT_PATH',
                                    state: { from: props.location }
                                } }
                            />
                        )
            }
        />
    )
};

并且当您使用这些组件时,请确保将 isAuthenticatedisVerifying 变量传递给您的 ProtectedRoute。像这样:

Router.js

const mapStateToProps = state => {

    return {
        isAuthenticated: state.auth.isAuthenticated,
        isVerifying: state.auth.isVerifying,
    };
}




<PrivateRoute
    exact
    path='PROTECTED_PATH'
    component={ DashboardPage }
    isAuthenticated={ isAuthenticated }
    isVerifying={ isVerifying }
/>

如果您对我的代码有任何疑问,请告诉我。

根据 ,解决方案是向组件添加 if 语句,该语句呈现加载,直到组件从服务器获得响应。所以我将默认操作值从 false 更改为 null 并添加 if 语句。在我的代码中它看起来像这样:

function ProtectedRoute({component: Component, isAuth, ...rest}){

    //Whaiting until gets response from server
    if (isAuth === null) {
        return 'loading..'
    }
    
    return (
        <Route 
            {...rest}
            render={(props) => {
                if(isAuth){
                    console.log('protected if')
                    return <Component {...props} />
                } else {
                    return <Redirect to={{
                        pathname: '/forbidden',
                        state: {from: props.location}
                    }}
                    />
                }
            }}
        />
    )
}

const mapStateToProps = (state) => {
    return {
        isAuth: state.userLoginReducer.userLogin
    }
}

export default connect(mapStateToProps)(ProtectedRoute)

我不确定这是处理这个问题的最佳方法,但它似乎解决了我的头痛。