首页 > 解决方案 > 使用 React-router-dom 和 Redux useSelector hook 保护路由

问题描述

我正在尝试保护我的一些路线,因为您必须经过身份验证才能定向到该路线。我将我的路由包装在一个执行一些验证的 routerWrapper 函数中,然后在验证后它重定向到正确的路由。我正在使用 useSelector 检查我的 authState,然后如果路由 isPrivate 和 isAuthenticated 我重定向到该路由,但毫无疑问地在第一个 React 渲染时我得到 isAuthenticated 为假,因此该函数正在返回登录路由。这是我的代码

const RouteWrapper = ({component, isPrivate, ...props}: IRoutProps) => {
    //Add another property to check isAdmin
    const state = useSelector((state: AppState) => state.auth);
    const {isAuthenticated} = state;
    console.log(isAuthenticated);

    if (isPrivate) {
        if (!state.isAuthenticated) {
            console.log('Private');
            return <Redirect to="/login" />;
        } else {
            return <Route {...props} component={component} />;
        }
    } else {
        if (
            props.path === '/login' &&
            state.isAuthenticated === true &&
            (state.user.type === 'Instructor' || state.user.type === 'Student')
        ) {
            return <Redirect to="/" />;
        } else if (
            props.path === '/admin/login' &&
            state.isAuthenticated &&
            state.user.type === 'Admin'
        ) {
            return <Redirect to="/admin/dashboard" />;
        }
        return <Route {...props} component={component} />;
    }
};

标签: reactjsreact-reduxreact-router-dom

解决方案


解决此问题的一种方法是status在您的状态中添加类似的内容。现在,此状态可能是以下状态之一idle(初始化时)、fetching(仍在确定用户是否已通过身份验证时)和processed(已完成身份验证,现在我们知道结果)。

您需要在代码的不同部分设置不同的状态。例如,在您设置的地方isAuthenticated,您需要在设置fetching之前将您的状态设置为isAuthenticated,一旦解决,您需要将您的状态设置为processed

这样我们就知道一旦状态变为processed,我们就会得到我们的isAuthenticated值,然后我们就可以继续我们的逻辑了。

如果我们继续将状态添加到您的状态,那么我们可以将我们的代码修改为类似这样

const RouteWrapper = ({component, isPrivate, ...props}: IRoutProps) => {
    const state = useSelector((state: AppState) => state.auth);
    const {isAuthenticated, status, user} = state;

    if (status === 'processed') {
       if (isPrivate) {
            return isAuthenticated ? 
             (<Route {...props} component={component} />) :
             (<Redirect to="/login" />)
       } else {
        if (
            props.path === '/login' &&
            isAuthenticated &&
            (user.type === 'Instructor' || user.type === 'Student')
        ) {
            return <Redirect to="/" />;
        } else if (
            props.path === '/admin/login' &&
            isAuthenticated &&
            user.type === 'Admin'
        ) {
            return <Redirect to="/admin/dashboard" />;
        }
    
        return <Route {...props} component={component} />;
      }
    }
};

这应该避免在确定用户是否通过身份验证之前isAuthenticated初始化组件时首次渲染组件。false


推荐阅读