Аутентификация пользователя в React Router - PullRequest
0 голосов
/ 07 марта 2020

люди. Я изучаю, как интегрировать React с Express с помощью React Router, и столкнулся с проблемой аутентификации пользователей. Я пытаюсь использовать компонент более высокого порядка для условного рендеринга защищенного маршрута на основе статуса авторизации пользователя.

const ProtectedRoute = ({ component: Component, ...rest }) => {
  return (
    <Route
      {...rest}
      render={props => {
        if (!AUTHORIZED) {
          return <Redirect to="/login" />;
        }
        return <Component {...props} />;
      }}
    />
  );
};

Проблема, с которой я столкнулся, заключается в операторе if (!AUTHORIZED). Я использую Passport для обработки аутентификации на стороне сервера Express, и у меня настроена конечная точка для получения информации о пользователе и статуса авторизации, но я не могу понять, как получить доступ к этим данным до визуализации страницы. Если бы я использовал компонент класса вместо функционального компонента (также изучая хуки), я думаю, что я мог бы получить данные с помощью метода жизненного цикла componentWillMount, но я прочитал, что это плохая практика. Буду очень признателен за любые идеи о том, как мне двигаться дальше!

*** edit *** Несколько вещей, которые я пытался заставить это работать ... Я попытался добавить модуль авторизации, чтобы получить данные для меня.

class Auth {
  constructor() {
    this.authenticated = false;
  }

  async isAuthenticated() {
    console.log("hitting auth route");
    await fetch("/api/auth")
      .then(res => res.json())
      .then(json => {
        if (json.error) {
          this.authenticated = false;
        }
        this.authenticated = true;
      });
    return this.authenticated;
  }
}

export default new Auth();

Я импортирую модуль и подключаю auth.authenticated() вместо заполнителя AUTHORIZED. Эта функция пропускается, потому что она асинхронная, и перенаправление всегда будет происходить. Поэтому мне нужно добавить await к auth.authenticated(). Но теперь мне нужно иметь async дальше по цепочке, поэтому я по глупости добавляю async перед props, например: render={async props => { Так что теперь он пытается визуализировать объект обещания вместо компонента, и мы получите ошибку Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead. Обещания до конца.

1 Ответ

0 голосов
/ 09 марта 2020

Ответ на этот вопрос в случае, если кто-то столкнется с подобной проблемой ... Первое решение, которое у меня было, было основано на комментарии Firealem Erko . При входе в систему я сохранил переменную с идентификатором пользователя в локальном хранилище и сослался на нее в своем компоненте. Это было хорошее первое решение, но позже оно было улучшено чем-то rotimi-best , упомянутым в его комментарии. Оказывается, вы действительно можете передавать реквизиты этим компонентам, чего я не осознавал в своей неопытности. Так что теперь я так делаю. Окончательное решение выглядит следующим образом:

const ProtectedRoute = ({
  component: Component,
  logged,
  setLogged,
  ...rest
}) => {
  return (
    <Route
      {...rest}
      render={props => {
        if (!logged) {
          return (
            <Redirect
              to={{
                pathname: "/login",
                state: { flashInfo: "Please log in to continue." }
              }}
            />
          );
        } else {
          return <Component {...props} logged={logged} setLogged={setLogged} />;
        }
      }}
    />
  );
};

А вот родительский компонент, который я передаю в реквизитах:

function App() {
  let [logged, setLogged] = useState(false);

  useEffect(() => {
    if (window.localStorage.getItem("qrs")) {
      setLogged(true);
    } else {
      setLogged(false);
    }
  }, []);

  return (
    <div className="App">
      <BrowserRouter>
        <Nav logged={logged} setLogged={setLogged} />
        <Switch>
          <ProtectedRoute
            exact
            path="/dashboard"
            component={Dashboard}
            logged={logged}
            setLogged={setLogged}
          />
          <Route
            path="/register"
            exact
            render={props => <Register {...props} logged={logged} />}
          />
          <Route
            path="/login"
            exact
            render={props => (
              <Login {...props} logged={logged} setLogged={setLogged} />
            )}
          />
        </Switch>
      </BrowserRouter>
    </div>
  );
}

Спасибо всем комментаторам за их предложения!

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