Как сохранить состояние постоянным, используя локальное хранилище, перехватчики реагирования и провайдер контекста - PullRequest
2 голосов
/ 07 ноября 2019

Я внедряю аутентификацию в свое приложение, проблема с обновлением состояния не является постоянной, поэтому я перенаправлен обратно на экран входа в систему. Как я могу использовать React Hooks, чтобы проверить, есть ли authToken в local storage, чтобы держать меня в системе при обновлении.

Это Мой защищенный маршрут Проверяет токены аутентификации

<Route
    {...rest}
    render={
        props=>
            authTokens ? (
                <Component {...props}/>
            ) : (
                <Redirect
                    to ={
                        {
                            pathname: '/login',
                            state: {
                                from: props.location
                            }
                        }
                    }
                />

Это моя Страница входа Функция

 function Login(props) {
const [isLoggedIn, setLoggedIn] = useState(false);
const [isError, setIsError] = useState(false);
const [firstName, setUserName] = useState("");
const [password, setPassword] = useState("");
const { setAuthTokens } = useAuth();

function postLogin() {
    axios.post("http://10.6.254.22:5000/userinformation/login", {
      firstName,
      password
    }).then(result => {
      if (result.status === 200) {
        console.log('You have been logged in as user: ' +result.data[0].firstName)
        setAuthTokens(result.data);
        setLoggedIn(true);
      } else {
        setIsError(true);
      }
    }).catch(e => {
      setIsError(true);
    });
  }


  if (isLoggedIn) {
    return <Redirect to="/" />;
  }

Ниже мой Крюк , который содержит состояние

    const [authTokens, setAuthTokens] = useState();

  const setTokens = (data) => {
    localStorage.setItem("authTokens", JSON.stringify(data));
    setAuthTokens(data);
  }

  useEffect(()=> {
    let jsonToken = localStorage.getItem('authTokens', JSON.stringify(authTokens))
    console.log('JSON TOKEN  -----' + jsonToken)
    setAuthTokens(jsonToken)
  })

Как я могу установить состояние authTokens с переменной local storage при загрузке, чтобы, когда яобновить состояние не пусто, так что я не выйду из системы при перезагрузке страницы. Также стоит упомянуть, что провайдер контекста настроен так:

<AuthContext.Provider value={{ authTokens, setAuthTokens: setTokens}}>
   <ProtectedRoute path="/" exact component={ProfileBox}/>
</AuthContext.Provider>

Ответы [ 2 ]

1 голос
/ 07 ноября 2019

Проблема в том, что authTokens равен undefined, когда ваш компонент монтируется , поэтому логика вашего Защищенного маршрута оценивается как часть Redirect вашего кода,вызывая перенаправление на /login.

React удалит хук componentWillMount, поэтому решение, которое я нашел для этой конкретной проблемы, состоит в том, чтобы проверить также токен в localStorage вместо простой проверкидля состояния authTokens.

Таким образом, ваш код сможет оценить, что у вас есть токен (даже до первого обновления компонента).

Код вашего Protected Routeможет выглядеть так:

<Route
    {...rest}
    render={
        props=>
            (authTokens || localStorage.getItem("authTokens")) ? (
                <Component {...props}/>
            ) : (
                <Redirect
                    to ={
                        {
                            pathname: '/login',
                            state: {
                                from: props.location
                            }
                        }
                    }
                />

Другие возможные решения:

  • Использование контекста
  • Использование Redux

Но я думаючто если вы просто хотите защитить частные маршруты, этого решения достаточно

1 голос
/ 07 ноября 2019

Вы можете создать хук , который проверяет, что localstorage содержит токен , если он не существует, пользователь не аутентифицирован, поэтому вы можете перенаправить его на logIn , иначе пользователь может получить доступ к ProtectedRoutes.

Возможно, вы сможете повторно использовать hook внутри компонента ProtectedRoute и обрабатывать его только там.

ProtectedRoute

Допустим, ваш компонент Логин - это страница, которую вы хотите перенаправить, если пользователь не auth. И скажем, вы используете react-router или что-то еще для обработки маршрутов и перенаправлений.

const ProtectedRoute = ({component, ...options}) => {
   const [isAuth ] = useAuth();
   let conditionalComponent = Login;
   if( isAuth ){
     conditionalComponent = component;
   }
   return <Route {...options} component={conditionalComponent} />
}

useAuth


const useAuth = () => {
 let [isAuth, handleAuthorized] = useStaet(false);

 useEffect( () => {
   if( checkLocalStorageToken() ){
    handleAuthorized( true );
   }  
   else {
    handleAuthorized(false)
   }
  return [ isAuth ]
 }, [ checkLocalStorageToken() ]);

}

Я использовал этошаблон и работает хорошо, я надеюсь, что смогу поделиться основной идеей, чтобы вы могли реализовать ее в своем случае.

...