Проверьте, вошел ли в систему — Реагирует маршрутизатор — Перенаправление

#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>

)