用React处理身份验证的最佳方法是什么?

问题描述

我有一个ProtectedRoute组件:

import React,{ useState,useEffect,useContext } from 'react';
import CreateRecipe from "./components/CreateRecipe";
import Login from "./components/Login";
import Register from "./components/Register";
import UserContext from './contexts/UserContext';
import Homepage from './components/Homepage';
import LandingPage from './components/LandingPage';
import EditRecipe from './components/EditRecipe';
import SearchPage from './components/SearchPage';
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,loading: true });
  const { auth } = useContext(UserContext.context);

  //async call to check authentication status
  useEffect(() => {
    axios.get('/authUser').then(res => {
      setAuthCheck({ isAuth: res.data.isAuth,loading: false });
    });
  },[]);

  return (

    <Route {...rest} render={(props) =>
      (!authCheck.loading) ? (authCheck.isAuth || auth) ? (<Component {...props} />) : (<Redirect to={{
        pathname: "/login",state: { from: props.location },}} />)
        : (<div>loading</div>)
    } />
  );

}

function App() {

  return (
    <div>
      <BrowserRouter>
        <UserContext>
          <ProtectedRoute component={Homepage} path="/:username/home" />
          <ProtectedRoute path='/:username/edit/:id' component={EditRecipe} />
          <ProtectedRoute path='/:username/create' component={CreateRecipe} />
          <ProtectedRoute path='/:username/search/:q' component={SearchPage} />
          <ProtectedRoute path='/:username/view/:id' component={ViewRecipe} />
          <Route path='/login' component={Login} />
        </UserContext>
        <Route path='/register' component={Register} />
        <Route exact path="/" component={LandingPage} />
      </BrowserRouter>
    </div>
  );
}

export default App;

我发现useEffect钩子甚至在呈现组件之前就触发了。这会导致authCheck.isAuth永久为假,从而阻止用户登录。为了解决这个问题,我使登录组件更新了上下文的身份验证状态。

如何解决useEffect问题?另外,是否有更好的方法在客户端设置身份验证?

解决方法

.then()重构为async await。它应该正确更新isAuth状态,然后您可以删除auth上下文。

const getAuthUser = async() => {
  try {
    const res = await axios.get('/authUser');
    setAuthCheck({ isAuth: res.data.isAuth,loading: false });
  } catch (e) {
    // handle the error
  } 
};

//async call to check authentication status
useEffect(() => {
  getAuthUser();
},[]);


return (

  <Route {...rest} render={(props) =>
    !authCheck.loading ? authCheck.isAuth ? (<Component {...props} />) : 
    (<Redirect to={{
      pathname: "/login",state: { from: props.location },}} />)
    : (<div>loading</div>)
   />
);

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...