#javascript #reactjs #asynchronous
#javascript #reactjs #асинхронный
Вопрос:
У меня есть ProtectedRoute
компонент:
import React, { useState, useEffect, useContext } from 'react';
import CreateRecipe from "./components/CreateRecipe";
import Lo&in from "./components/Lo&in";
import Re&ister from "./components/Re&ister";
import UserContext from './contexts/UserContext';
import Homepa&e from './components/Homepa&e';
import Landin&Pa&e from './components/Landin&Pa&e';
import EditRecipe from './components/EditRecipe';
import SearchPa&e from './components/SearchPa&e';
import ViewRecipe from './components/ViewRecipe';
import { BrowserRouter, Route, Redirect } from 'react-router-dom';
import axios from 'axios';
/**
* Used for Routes that cannot be accessed without authentication
*/
function ProtectedRoute({ component: Component, ...rest }) {
const [authCheck, setAuthCheck] = useState({ isAuth: false, loadin&: true });
const { auth } = useContext(UserContext.context);
//async call to check authentication status
useEffect(() =&&t; {
axios.&et('/authUser').then(res =&&t; {
setAuthCheck({ isAuth: res.data.isAuth, loadin&: false });
});
}, []);
return (
<Route {...rest} render={(props) =&&t;
(!authCheck.loadin&) ? (authCheck.isAuth || auth) ? (<Component {...props} /&&t;) : (<Redirect to={{
pathname: "/lo&in",
state: { from: props.location },
}} /&&t;)
: (<div&&t;loadin&</div&&t;)
} /&&t;
);
}
function App() {
return (
<div&&t;
<BrowserRouter&&t;
<UserContext&&t;
<ProtectedRoute component={Homepa&e} path="/:username/home" /&&t;
<ProtectedRoute path='/:username/edit/:id' component={EditRecipe} /&&t;
<ProtectedRoute path='/:username/create' component={CreateRecipe} /&&t;
<ProtectedRoute path='/:username/search/:q' component={SearchPa&e} /&&t;
<ProtectedRoute path='/:username/view/:id' component={ViewRecipe} /&&t;
<Route path='/lo&in' component={Lo&in} /&&t;
</UserContext&&t;
<Route path='/re&ister' component={Re&ister} /&&t;
<Route exact path="/" component={Landin&Pa&e} /&&t;
</BrowserRouter&&t;
</div&&t;
);
}
export default App;
Я обнаружил, что перехват useEffect срабатывает еще до того, как компонент будет отрисован. Это приводит к тому, что authCheck.isAuth
значение постоянно принимает значение false, что не позволяет пользователю войти в систему. Чтобы обойти это, я заставил свой компонент входа обновить состояние аутентификации контекста.
Как бы мне обойти проблему useEffect? Кроме того, есть ли лучший способ настроить аутентификацию на стороне клиента?
Комментарии:
1. На самом деле,
useEffect
перехват запускается после рендеринга компонента. reactjs.or&/docs/hooks-effect.html
Ответ №1:
Реорганизуйте .then()
в async await
. Он должен корректно обновить isAuth
состояние, и тогда вы сможете удалить auth
контекст.
const &etAuthUser = async() =&&t; {
try {
const res = await axios.&et('/authUser');
setAuthCheck({ isAuth: res.data.isAuth, loadin&: false });
} catch (e) {
// handle the error
}
};
//async call to check authentication status
useEffect(() =&&t; {
&etAuthUser();
}, []);
return (
<Route {...rest} render={(props) =&&t;
!authCheck.loadin& ? authCheck.isAuth ? (<Component {...props} /&&t;) :
(<Redirect to={{
pathname: "/lo&in",
state: { from: props.location },
}} /&&t;)
: (<div&&t;loadin&</div&&t;)
/&&t;
);