Я пытаюсь реализовать аутентифицированные маршруты с помощью React и Typescript, однако я наткнулся на конкретный вариант использования. Для просмотра клиентов все работает нормально, однако, когда я вручную изменяю маршрут в браузере, контекст обновляется позже (после перенаправления моего маршрута), и в моем компоненте PrivateRoute больше не отображалось.
Чтобы избежать Для решения этой проблемы я добавил флаг isRendered, чтобы обеспечить четкое описание состояния (для флага isLoggedIn установлено значение true) перед показом маршрутов, однако я хочу знать основную причину и, если возможно, более четкое решение.
Контекст моего приложения
import React, { createContext, useState, useEffect } from 'react';
import { DEFAULT_APP_STATE } from 'utils/constants';
import { AppState, AppContextProps } from 'types';
import Cookies from 'universal-cookie';
const AppContext = createContext<AppState>(DEFAULT_APP_STATE);
const AppContextProvider: React.FunctionComponent<AppContextProps> = ({
children,
}) => {
const [username, setUsername] = useState<string>('');
const [userToken, setUserToken] = useState<string>('');
const [isSignedIn, setIsSignedIn] = useState<boolean>(false);
const [isRendered, setIsRendered] = useState<boolean>(false);
//effect that will ensure the login state after refresh
useEffect(() => {
const cookies = new Cookies();
const cookieUser = cookies.get('username');
const cookieToken = cookies.get('userToken');
if (cookieUser && cookieToken) {
setUsername(cookieUser);
setUserToken(cookieToken);
setIsSignedIn(true);
}
setIsRendered(true);
}, []);
return (
<AppContext.Provider
value={{
username,
userToken,
setUsername,
setUserToken,
isSignedIn,
setIsSignedIn,
}}
>
{isRendered && children}
</AppContext.Provider>
);
};
export default AppContextProvider;
export const useAppContext = () => React.useContext(AppContext);
Частный маршрут:
import React from 'react';
import { useAppContext } from './App/AppContext';
import { Redirect, Route, RouteProps } from 'react-router-dom';
import { ROUTES } from 'utils/constants';
const PrivateRoute: React.FunctionComponent<RouteProps> = routeProps => {
const { isSignedIn } = useAppContext();
return isSignedIn ? <Route {...routeProps} /> : <Redirect to={ROUTES.HOME} />;
};
export default PrivateRoute;