#javascript #reactjs
Вопрос:
У меня есть маршрутизатор React, где некоторые маршруты проверяют, вошел ли пользователь в систему. Функция вызывает серверную часть и возвращает либо true, либо false. Эта часть работает нормально, но когда я вызываю функцию для отображения запрошенного компонента или перенаправления, она всегда отображает перенаправление.
function requireAuth() {
axiosInst.post("http://localhost:3001/checkLogged")
.then(function (response) {
if (response.data.user) {
return true
}else{
return false
}
})
}
<Router>
<>
<Navigation/>
<Switch>
<Route path="/login/" exact component={Login} ></Route>
<Route path="/register/" exact component={Register} />
<Route path="/" exact component={Feed} />
<Route path="/articles/" exact component={Feed} />
<Route path="/profile/" >
{requireAuth() ? <Profile/> : <Redirect to="/" />}
</Route>
<Route path="/settings/" component={Settings} />
<Route path="/write/" >
{requireAuth() ? <Write/> : <Redirect to="/" />}
</Route>
<Route path="/search/" component={Search} />
<Route path="/articles/:id" component={ArticleView} />
</Switch>
</>
</Router>
Ответ №1:
Это происходит из requireAuth
-за асинхронности, и когда он возвращает логическое значение, React уже отрисовал перенаправление.
Почему бы вам не использовать переменную состояния? Что-то вроде:
const [auth, setAuth] = useState(false);
...
function requireAuth() {
axiosInst.post("http://localhost:3001/checkLogged")
.then(function (response) {
if (response.data.user) {
setAuth(true);
return true;
}else{
setAuth(false);
return false;
}
})
}
...
<Router>
<>
<Navigation/>
<Switch>
<Route path="/login/" exact component={Login} ></Route>
<Route path="/register/" exact component={Register} />
<Route path="/" exact component={Feed} />
<Route path="/articles/" exact component={Feed} />
<Route path="/profile/" >
{auth ? <Profile/> : <Redirect to="/" />}
</Route>
<Route path="/settings/" component={Settings} />
<Route path="/write/" >
{auth ? <Write/> : <Redirect to="/" />}
</Route>
<Route path="/search/" component={Search} />
<Route path="/articles/:id" component={ArticleView} />
</Switch>
</>
</Router>
Комментарии:
1. Правда. Таким образом, мне не нужно заключать его в функцию или просто немедленно вызывать функцию. Спасибо!!
2. Да, именно так. Рендеринг React работает с переменной состояния, поэтому, если вам нужно что-то сделать условно, вы должны использовать
useState
Ответ №2:
Вы совершаете ошибку внутри функции requireAuth. Внутри этой функции затем возвращается true/false, но функция requireAuth ничего не возвращает. Поэтому, чтобы функция requireAuth возвращала значение true/false, вы должны вернуть значение axios этой функции. А также axios возвращает обещания, поэтому для обработки обещаний рекомендуется использовать асинхронную функцию
async function requireAuth() {
return await axiosInst.post("http://localhost:3001/checkLogged")
.then(function (response) {
if (response.data.user) {
return true
}else{
return false
}
})
}
И измените свой код маршрута, чтобы:
....
const [auth, setAuth] = useState(false);
requireAuth().then((res)=>{setAuth(res)})
return(
<Router>
<>
<Navigation/>
<Switch>
<Route path="/login/" exact component={Login} ></Route>
<Route path="/register/" exact component={Register} />
<Route path="/" exact component={Feed} />
<Route path="/articles/" exact component={Feed} />
<Route path="/profile/" >
{auth ? <Profile/> : <Redirect to="/" />}
</Route>
<Route path="/settings/" component={Settings} />
<Route path="/write/" >
{auth ? <Write/> : <Redirect to="/" />}
</Route>
<Route path="/search/" component={Search} />
<Route path="/articles/:id" component={ArticleView} />
</Switch>
</>
</Router>
)