Как выполнить аутентификацию с помощью React hooks и react-router

#javascript #reactjs #react-hooks

#javascript #reactjs #react-перехваты

Вопрос:

Я пытаюсь аутентифицировать пользователя при каждом изменении маршрута с помощью react-router-dom и react hooks . Идея заключается в том, что каждый раз, когда пользователь переходит к маршруту, система выполняет вызов api и аутентифицирует пользователя. Мне нужно добиться этого, потому что я использую react-redux , и при каждой перезагрузке окна состояние redux не сохраняется. Итак, мне нужно снова установить для isLoggedNow prop значение true :

 const PrivateRoute = ({
  component: Component,
  checkOnEachRoute: checkReq,
  isUserLogged,
  ...rest
}) => {
  const [isLoggedNow, setLogged] = useState(isUserLogged);
  useEffect(
    () => {
      const fetchStatus = async () => {
        try {
          await selectisUserLogged();
          setLogged(true);
        } catch (error) {
          console.log(error);
        }
      };
      fetchStatus();
    },
    [isUserLogged],
  );
  return (
    <Route
      {...rest}
      render={props =>
        isLoggedNow ? (
          <div>
            <Component {...props} />
          </div>
        ) : (
          <Redirect
            to={{
              pathname: '/login',
            }}
          />
        )
      }
    />
  );
};
  

Затем я бы использовал вышеуказанное PrivateRoute следующим образом:

 function App(props) {
  return (
    <div>
      <Switch location={props.location}>
        <Route exact path="/login" component={Login} />
        <PrivateRoute exact path="/sidebar" component={Sidebar} />
      </Switch>
    </div>
  );
}
  

Сначала isUserLogged есть true , но после перезагрузки окна я получаю сообщение об ошибке Warning: Can't perform a React state update on an unmounted component.
Итак, как я могу добиться этого, чтобы при каждой перезагрузке окна я аутентифицировал пользователя? Я ищу какой-то componentWillMount .

Комментарии:

1. у вас была возможность решить эту проблему?

2. @camelCase да!

3. хотите поделиться? 🙂 на данный момент сталкиваюсь с точно такой же проблемой

4. @camelCase Смотрите мой ответ, это решает проблему для вас?:)

Ответ №1:

Что-то вроде этого работает (где isUserLogged это реквизит из redux):

 function PrivateRoute({ component: Component, isUserLogged, ...rest }) {
  const [isLoading, setLoading] = useState(true);
  const [isAuthenticated, setAuth] = useState(false);
  useEffect(() => {
    const fetchLogged = async () => {
      try {
        setLoading(true);
        const url = new URL(fetchUrl);
        const fetchedUrl = await fetchApi(url);
        setAuth(fetchedUrl.body.isAllowed);
        setLoading(false);
      } catch (error) {
        setLoading(false);
      }
    };
    fetchLogged();
  }, []);
  return (
    <Route
      {...rest}
      render={props =>
        // eslint-disable-next-line no-nested-ternary
        isUserLogged || isAuthenticated ? (
          <Component {...props} />
        ) : isLoading ? (
          <Spin size="large" />
        ) : (
          <Redirect
            to={{
              pathname: '/login',
            }}
          />
        )
      }
    />
  );
}
  

Комментарии:

1. Кажется, у меня тоже работает, просто есть вопрос, почему у вас isUserLogged передан в props?

2. @camelCase У меня была идея fetchLogged(); включить ìf(!isUserLogged)... , поэтому извлекать только в том случае, если не isUserLogged 🙂