我有一个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问题?另外,是否有更好的方法在客户端设置身份验证?
答案 0 :(得分:-1)
将.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>)
/>
);