使用钩子对Redux进行反应-身份验证和受保护的路由

时间:2020-03-20 15:42:27

标签: javascript reactjs redux redux-thunk

我正在使用带有钩子,react-redux和redux-thunk的React,但不确定是否正确进行了身份验证。在Main.js中,我正在调用名为checkIfLoggedIn()的操作。这是Main.js的内容:

class Main extends React.Component {
    constructor(props) {
        super(props);
        this.props.checkIfLoggedIn();

    }

    render() {
        return (
            <BrowserRouter>
                <div style={{position: 'relative'}}>
                    <Navbar/>
                    <div className={'container-fluid'}>
                        <Route exact path={'/'} component={(Dashboard)}/>
                        <Route exact path={'/sale'} component={(Sale)}/>
                        <Route exact path={'/settings'} component={(Settings)}/>
                        <Route exact path={'/login'} component={(Login)}/>
                    </div>
                </div>
            </BrowserRouter>
        )
    }
}

const mapDispatchToProps = {
    checkIfLoggedIn
};

export default connect(null, mapDispatchToProps)(Main);

这是checkIfLoggedIn()

的代码
import {SET_ADMIN, SET_LOGGED_IN} from "./types";
import axios from 'axios';

export const checkIfLoggedIn = () => async dispatch => {
    const adminToken = window.localStorage.getItem('admin_token');
    if (adminToken === null)
        dispatch({
            type: SET_LOGGED_IN,
            payload: false
        });
    else {
        try {
            const r = await axios.get('/users/me');
            const data = r.data;
            dispatch({
                type: SET_ADMIN,
                payload: data
            });
            dispatch({
                type: SET_LOGGED_IN,
                payload: true
            });

        } catch (e) {
            dispatch({
                type: SET_LOGGED_IN,
                payload: false
            });
        }
    }
};

还有我的初始状态:

const initialState = {
    isLoggedIn: false,
    currentAdmin: {
    },
};

现在,我想创建一条ProtectedRoute,当我未登录时将其重定向到登录路由。我想在Login组件中进行类似的操作,将我重定向到{{1} }路由(如果我已登录。

但是在两种情况下,我的属性isLoggedIn最初都设置为false,并在几毫秒后更新。这是我的Login组件代码,无法正常运行:

'/'

该表格会显示一会儿,然后我被重定向到主要路线。如何防止显示表单?以及如何让PrivateRoute等待片刻以接收所有道具并获得初始isLoggedIn状态?

1 个答案:

答案 0 :(得分:0)

不确定我是否完全了解您正在做的事情,但这是我的想法。在您的useEffect中,isLoggedIn布尔值似乎正在控制重定向布尔值,这可能会导致有害的副作用。

改为尝试

const Login = props => {

    const dispatch = useDispatch();
    const [redirect, setRedirect] = useState(false);

    dispatch(checkIfLoggedIn());

    useEffect(() => {
            // If user is not logged in, redirect them
            if (!props.isLoggedIn) {
            setRedirect(true)
     }

    }, [props.isLoggedIn]);

    return redirect ? <Redirect to={'/'} /> : (
    /* the login form code */
    )
}

如果您使用的是react-router,并且使用withRouter高阶组件导出此组件,则最好使用history.push来完成您的工作

const Login = props => {

    const dispatch = useDispatch();
    const [redirect, setRedirect] = useState(false);

    dispatch(checkIfLoggedIn());

    useEffect(() => {
            // If user is not logged in, redirect them
            if (!props.isLoggedIn) {
            props.history.push('/redirectRoute')
     }

    }, [props.isLoggedIn]);

    return redirect ? <Redirect to={'/'} /> : (
    /* the login form code */
    )
}