Функциональный компонент PrivateRoute, использующий aws -amplify в качестве аутентификации - PullRequest
0 голосов
/ 28 марта 2020

Я пытаюсь создать функциональный компонент, эквивалентный следующему компоненту класса PrivateRoute (исходный код здесь ):

import React, { useState, useEffect } from "react";
import { Route, Redirect, withRouter, useHistory } from "react-router-dom";
import { Auth } from "aws-amplify";

class PrivateRoute extends React.Component {
  state = {
    loaded: false,
    isAuthenticated: false
  };
  componentDidMount() {
    this.authenticate();
    this.unlisten = this.props.history.listen(() => {
      Auth.currentAuthenticatedUser()
        .then(user => console.log("user: ", user))
        .catch(() => {
          if (this.state.isAuthenticated)
            this.setState({ isAuthenticated: false });
        });
    });
  }
  componentWillUnmount() {
    this.unlisten();
  }
  authenticate() {
    Auth.currentAuthenticatedUser()
      .then(() => {
        this.setState({ loaded: true, isAuthenticated: true });
      })
      .catch(() => this.props.history.push("/auth"));
  }
  render() {
    const { component: Component, ...rest } = this.props;
    const { loaded, isAuthenticated } = this.state;
    if (!loaded) return null;
    return (
      <Route
        {...rest}
        render={props => {
          return isAuthenticated ? (
            <Component {...props} />
          ) : (
            <Redirect
              to={{
                pathname: "/auth"
              }}
            />
          );
        }}
      />
    );
  }
}

export default withRouter(PrivateRoute);

Приведенный выше код работает в моем приложении, когда я использую это так:

<PrivateRoute
  exact
  path={urls.homepage}
  component={Homepage}
/>

Моя попытка преобразовать вышеуказанный компонент класса в функциональный компонент заключается в следующем:

import React, { useState, useEffect } from "react";
import { Route, Redirect, useHistory } from "react-router-dom";
import { Auth } from "aws-amplify";

const PrivateRoute = ({ component: Component, ...rest }) => {
  const [isLoaded, setIsLoaded] = useState(false);
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  let history = useHistory();

  useEffect(() => {
    Auth.currentAuthenticatedUser()
      .then(() => {
        setIsLoaded(true);
        setIsAuthenticated(true);
      })
      .catch(() => history.push("/auth"));

    return () =>
      history.listen(() => {
        Auth.currentAuthenticatedUser()
          .then(user => console.log("user: ", user))
          .catch(() => {
            if (isAuthenticated) setIsAuthenticated(false);
          });
      });
  }, [history, isAuthenticated]);

  if (!isLoaded) return null;

  return (
    <Route
      {...rest}
      render={props => {
        return isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/auth"
            }}
          />
        );
      }}
    />
  );
};

export default PrivateRoute;

Но при использовании моего функционального компонента таким же образом, Я получаю следующее сообщение об ошибке:

Предупреждение. Не удается выполнить обновление состояния React для отключенного компонента. Это неоперация, но она указывает на утечку памяти в вашем приложении. Чтобы исправить, отмените все подписки и асинхронные задачи в функции очистки useEffect

Она всегда перенаправляет меня в / auth, независимо от того, вошел я в систему или нет. Что я делаю неправильно? Любая помощь очень ценится!

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