ReactJS: визуализация приватного маршрута, если аутентификация выполнена после выполнения обещания - PullRequest
1 голос
/ 08 февраля 2020

У меня есть PrivateRoute функциональный компонент, который решает визуализировать компонент, который был передан как реквизит для пользователя, к которому он имеет доступ, на основе его аутентификации или перенаправления на неавторизованный маршрут.

isValidToken - это асинхронная c функция , проверяет, есть ли у пользователя действительный токен или нет, и возвращает логическое значение , назначенное isUserLogged .so, когда я вызвал эту функцию в useEffect перехватывает ее ожидание разрешения функции, но до ее завершения происходит перенаправление. так как же я жду, пока он не разрешится и не отрендерится на основе этого значения, прежде чем разрешится обещание?

import React, { useState, useEffect } from "react";
import { Route, Redirect } from "react-router-dom";
import isValidToken from "../utils/isValidToken";

const ProtectedRoute = ({ component: Comp, path, redirectto, ...rest }) => {
  const [isloggedin, setloggedin] = useState(false);

  useEffect(() => {
    (async function() {
      const isUserLogged = await isValidToken();
      setloggedin(isUserLogged);
    })();
  }, []);

  return (
    <Route
      path={path}
      {...rest}
      render={props => {
        return isloggedin ? (
          <Comp {...props} />
        ) : (
          <Redirect to={redirectto} />
          // <h1>404 error</h1>
        );
      }}
    />
  );
};

export default ProtectedRoute;

Ответы [ 2 ]

2 голосов
/ 08 февраля 2020

Чтобы избежать преждевременного перенаправления, ваш компонент должен учитывать «состояние ожидания» обещания (это стоит за вашим вызовом функции asyn c).

В состоянии ожидания (или «загрузки») вы обычно визуализируете нечто вроде загрузочного счетчика, чтобы указать пользователю, что приложение занято. Ключ заключается в том, чтобы не отображать компонент <Comp /> или <Redirect />, пока обещание не будет разрешено (или отклонено):

import React, { useState, useEffect } from "react";
import { Route, Redirect } from "react-router-dom";
import isValidToken from "../utils/isValidToken";

const ProtectedRoute = ({ component: Comp, path, redirectto, ...rest }) => {

  /* Track the state of your app instead. Start with a "loading" state */
  const [state, setState] = useState('loading');

  useEffect(() => {
    (async function() {
      try {
        /* Update effect logic to track correct state */
        const isUserLogged = await isValidToken();
        setState(isUserLogged ? 'loggedin' : 'redirect');
      }
      catch {
        setState('redirect');
      }
    })();
  }, []);
  
  /* If in loading state, return loading message while waiting for 
  isValidToken to complete */
  if(state === 'loading') {
    return <div>Loading..</div>
  }

  return (
    <Route
      path={path}
      {...rest}
      {/* Decide what component to render based on state */
      render={props => ((state === 'loggedin') ? 
        <Comp {...props} /> : 
        <Redirect to={redirectto} />) }
    />
  );
};

export default ProtectedRoute;
0 голосов
/ 08 февраля 2020

Попробуйте это:

import React, { useState, useEffect } from "react";
import { Route, Redirect } from "react-router-dom";
import isValidToken from "../utils/isValidToken";

const ProtectedRoute = ({ component: Comp, path, redirectto, ...rest }) => {
  const [isloggedin, setloggedin] = useState(false);

  const [redirectTo, setRedirectTo] = useState(null);

  useEffect(() => {
    (async function() {
      const isUserLogged = await isValidToken();
      setloggedin(isUserLogged);
      setRedirectTo('/route');
    })();
  }, []);

  if (redirectTo && isloggedin) {
      return <Redirect to={redirectTo} />
  }

  return (
    <Route
      path={path}
      {...rest}
      render={props => <Comp {...props} />}
    />
  );
};

export default ProtectedRoute;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...