【问题标题】:Protected router doesn't re-render when Redux state updateRedux 状态更新时,受保护的路由器不会重新渲染
【发布时间】:2020-12-14 20:52:36
【问题描述】:

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

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)

【问题讨论】:

    标签: javascript reactjs api redux router


    【解决方案1】:

    也许你可以使用下面的“browserHistory”来重定向。

    import { browserHistory } from 'react-router'
    
    // ...
    else {
           console.log('protected else')
           return browserHistory.push('/forbidden');
         }
    
    

    【讨论】:

    • 这不是我的问题的答案,因为正如我所说,默认状态默认值为false,这意味着它始终重定向到'/forbidden',但如果状态更新为true,它应该允许使用受保护的组件。问题是状态更新到true'组件后没有重新渲染,也没有看到状态是true
    • 对不起,我误会了。
    【解决方案2】:

    我也有类似的问题。

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

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

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

    我会给你一些例子。

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

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

    【讨论】:

    • 我不明白向 Redux 添加另一个操作如何有助于重新渲染?它也不起作用。
    • 当您的操作被触发时,它将更改您的商店状态。然后你的整个应用程序将重新渲染。
    • 好的,我正在使用这个逻辑:当应用程序启动时,他检查服务器上的令牌状态。意味着在整个应用程序呈现时。当应用程序从服务器获得一切正常且用户已通过身份验证的响应时,他会调度操作并设置为true,根据您的说法,它应该重新渲染整个应用程序,但事实并非如此。我的 ProtectedRoute 组件不会重新渲染
    【解决方案3】:

    根据this post 的解决方案是在组件中添加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)
    

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

    【讨论】:

      猜你喜欢
      • 2019-05-07
      • 1970-01-01
      • 2020-07-26
      • 2021-06-22
      • 1970-01-01
      • 2017-12-23
      • 1970-01-01
      • 2020-03-03
      • 1970-01-01
      相关资源
      最近更新 更多