Реагировать на контекст и аутентифицированные маршруты - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь реализовать аутентифицированные маршруты с помощью 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;
...