如何使用本地存储、反应挂钩和上下文提供程序保持状态持久
How do I keep state persistant using local storage, react hooks, and Context Provider
我正在我的应用程序中实施身份验证,我遇到的问题是刷新状态不是持久的,所以我被重定向回登录屏幕。我如何使用 React Hooks 检查 local storage
中是否有 authToken 让我在刷新时保持登录状态。
这是我的受保护路由,用于检查身份验证令牌
<Route
{...rest}
render={
props=>
authTokens ? (
<Component {...props}/>
) : (
<Redirect
to ={
{
pathname: '/login',
state: {
from: props.location
}
}
}
/>
这是我的登录页面功能
function Login(props) {
const [isLoggedIn, setLoggedIn] = useState(false);
const [isError, setIsError] = useState(false);
const [firstName, setUserName] = useState("");
const [password, setPassword] = useState("");
const { setAuthTokens } = useAuth();
function postLogin() {
axios.post("http://10.6.254.22:5000/userinformation/login", {
firstName,
password
}).then(result => {
if (result.status === 200) {
console.log('You have been logged in as user: ' +result.data[0].firstName)
setAuthTokens(result.data);
setLoggedIn(true);
} else {
setIsError(true);
}
}).catch(e => {
setIsError(true);
});
}
if (isLoggedIn) {
return <Redirect to="/" />;
}
下面是我的 Hook 包含状态
const [authTokens, setAuthTokens] = useState();
const setTokens = (data) => {
localStorage.setItem("authTokens", JSON.stringify(data));
setAuthTokens(data);
}
useEffect(()=> {
let jsonToken = localStorage.getItem('authTokens', JSON.stringify(authTokens))
console.log('JSON TOKEN -----' + jsonToken)
setAuthTokens(jsonToken)
})
如何在加载时使用 local storage
变量设置状态 authTokens 以便在刷新状态时状态不为空,这样我就不会在页面重新加载时注销.还要提一下 context provider 是这样设置的:
<AuthContext.Provider value={{ authTokens, setAuthTokens: setTokens}}>
<ProtectedRoute path="/" exact component={ProfileBox}/>
</AuthContext.Provider>
您可以创建一个 hook 检查 localstorage
是否包含 token,如果它不存在用户未通过身份验证,因此您可以将他重定向到 logIn,否则用户可以访问 ProtectedRoutes
.
也许您可以在 ProtectedRoute
组件中重用 钩子 并在那里处理它。
ProtectedRoute
假设您的组件 Login 是您想要在用户不是 auth
时重定向的页面。假设您正在使用 react-router
或其他东西来处理路由和重定向。
const ProtectedRoute = ({component, ...options}) => {
const [isAuth ] = useAuth();
let conditionalComponent = Login;
if( isAuth ){
conditionalComponent = component;
}
return <Route {...options} component={conditionalComponent} />
}
useAuth
const useAuth = () => {
let [isAuth, handleAuthorized] = useState(false);
useEffect( () => {
if( checkLocalStorageToken() ){
handleAuthorized( true );
}
else {
handleAuthorized(false)
}
return [ isAuth ]
}, [ checkLocalStorageToken() ]);
}
我已经使用过这个模式并且效果很好,我希望我可以分享主要想法,以便您可以根据自己的情况实施它。
问题是当你的组件mounts时authTokens
是undefined
,所以你的Protected route[=37]的逻辑=] 正在评估代码的 Redirect
部分,导致重定向到 /login
.
React 将删除 componentWillMount
挂钩,因此,我发现针对此特定问题的解决方案是还要检查 localStorage
中的令牌,而不是仅检查状态 authTokens
.
这样,您的代码将能够评估您是否拥有令牌(甚至在第一次组件更新之前)。
您的 Protected Route
代码可能如下所示:
<Route
{...rest}
render={
props=>
(authTokens || localStorage.getItem("authTokens")) ? (
<Component {...props}/>
) : (
<Redirect
to ={
{
pathname: '/login',
state: {
from: props.location
}
}
}
/>
其他可能的解决方案是:
- 使用上下文
- 使用 Redux
但我觉得如果你只是想保护私有路由,这个方案就足够了
我正在我的应用程序中实施身份验证,我遇到的问题是刷新状态不是持久的,所以我被重定向回登录屏幕。我如何使用 React Hooks 检查 local storage
中是否有 authToken 让我在刷新时保持登录状态。
这是我的受保护路由,用于检查身份验证令牌
<Route
{...rest}
render={
props=>
authTokens ? (
<Component {...props}/>
) : (
<Redirect
to ={
{
pathname: '/login',
state: {
from: props.location
}
}
}
/>
这是我的登录页面功能
function Login(props) {
const [isLoggedIn, setLoggedIn] = useState(false);
const [isError, setIsError] = useState(false);
const [firstName, setUserName] = useState("");
const [password, setPassword] = useState("");
const { setAuthTokens } = useAuth();
function postLogin() {
axios.post("http://10.6.254.22:5000/userinformation/login", {
firstName,
password
}).then(result => {
if (result.status === 200) {
console.log('You have been logged in as user: ' +result.data[0].firstName)
setAuthTokens(result.data);
setLoggedIn(true);
} else {
setIsError(true);
}
}).catch(e => {
setIsError(true);
});
}
if (isLoggedIn) {
return <Redirect to="/" />;
}
下面是我的 Hook 包含状态
const [authTokens, setAuthTokens] = useState();
const setTokens = (data) => {
localStorage.setItem("authTokens", JSON.stringify(data));
setAuthTokens(data);
}
useEffect(()=> {
let jsonToken = localStorage.getItem('authTokens', JSON.stringify(authTokens))
console.log('JSON TOKEN -----' + jsonToken)
setAuthTokens(jsonToken)
})
如何在加载时使用 local storage
变量设置状态 authTokens 以便在刷新状态时状态不为空,这样我就不会在页面重新加载时注销.还要提一下 context provider 是这样设置的:
<AuthContext.Provider value={{ authTokens, setAuthTokens: setTokens}}>
<ProtectedRoute path="/" exact component={ProfileBox}/>
</AuthContext.Provider>
您可以创建一个 hook 检查 localstorage
是否包含 token,如果它不存在用户未通过身份验证,因此您可以将他重定向到 logIn,否则用户可以访问 ProtectedRoutes
.
也许您可以在 ProtectedRoute
组件中重用 钩子 并在那里处理它。
ProtectedRoute
假设您的组件 Login 是您想要在用户不是 auth
时重定向的页面。假设您正在使用 react-router
或其他东西来处理路由和重定向。
const ProtectedRoute = ({component, ...options}) => {
const [isAuth ] = useAuth();
let conditionalComponent = Login;
if( isAuth ){
conditionalComponent = component;
}
return <Route {...options} component={conditionalComponent} />
}
useAuth
const useAuth = () => {
let [isAuth, handleAuthorized] = useState(false);
useEffect( () => {
if( checkLocalStorageToken() ){
handleAuthorized( true );
}
else {
handleAuthorized(false)
}
return [ isAuth ]
}, [ checkLocalStorageToken() ]);
}
我已经使用过这个模式并且效果很好,我希望我可以分享主要想法,以便您可以根据自己的情况实施它。
问题是当你的组件mounts时authTokens
是undefined
,所以你的Protected route[=37]的逻辑=] 正在评估代码的 Redirect
部分,导致重定向到 /login
.
React 将删除 componentWillMount
挂钩,因此,我发现针对此特定问题的解决方案是还要检查 localStorage
中的令牌,而不是仅检查状态 authTokens
.
这样,您的代码将能够评估您是否拥有令牌(甚至在第一次组件更新之前)。
您的 Protected Route
代码可能如下所示:
<Route
{...rest}
render={
props=>
(authTokens || localStorage.getItem("authTokens")) ? (
<Component {...props}/>
) : (
<Redirect
to ={
{
pathname: '/login',
state: {
from: props.location
}
}
}
/>
其他可能的解决方案是:
- 使用上下文
- 使用 Redux
但我觉得如果你只是想保护私有路由,这个方案就足够了