我有一个身份验证服务,可以在成功登录后设置本地存储令牌
身份验证服务:
async function login(email, password, remember) {
const data = await ApiClient.post(`/api/auth`, {
email: email, password: password, remember: remember
});
localStorage.setItem('token', data.token);
return data.token;
}
async function logout() {
localStorage.removeItem('token');
}
export const authenticationService = {
login,
logout,
get currentUserValue () { return localStorage.getItem('token') }
}
App.js
{ authenticationService.currentUserValue &&
<Menu>Logged In</Menu> }
<Switch>
<PrivateRoute path="/dashboard" component={Dashboard} />
<Route path="/login" component={Login} />
<Route component={Error404} />
</Switch>
Login.js
async function login(e) {
e.preventDefault();
try {
const token = await authenticationService.login(email, password, remember);
setErrorMsg('');
history.push('/dashboard');
} catch (err) {
if(err.response.status === 401) {
setErrorMsg('Unauthorized access, please login again.');
}
}
}
<form className={classes.form} noValidate onSubmit={login}>
<TextField value={email} />
<TextField value={password} />
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
onChange={(e) => setRemember(e.target.value)}
value={remember}
/>
<Button type="submit">Sign In</Button>
</form>
当我使用Login.js
中的表单登录时,它不会呈现<Menu>Logged In</Menu>
中的菜单App.js
。当我们在本地存储get currentUserValue () { return localStorage.getItem('token') }
中设置令牌值并登录后呈现菜单时,是否可以重新渲染?
答案 0 :(得分:2)
您需要将令牌存储在某种状态下。然后根据令牌的状态呈现视图。
创建钩子并分离一些问题。身份验证现在需要获取并存储令牌。在这些挂钩中将这两个拆分:存储挂钩和身份验证挂钩。
存储挂钩将创建您读写令牌的状态。它还根据令牌中的值更新localStorage
项。
返回token
和setToken
函数供其他组件或挂钩使用。
const useTokenStorage = () => {
const [ token, setToken ] = useState(() => {
const token = localStorage.getItem('token');
return token !== null ? token : ''
});
useEffect(() => {
if (token === '') {
localStorage.removeItem('token');
} else {
localStorage.setItem('token', token);
}
}, [token]);
return [ token, setToken ];
};
身份验证服务挂钩将使用存储挂钩来设置令牌的值。 login
和logout
函数将用token
更新setToken
的值,而localStorage
则将更新token
。
从挂钩中返回login
,logout
和token
函数,因此login
仅可通过logout
和{{1 }} 职能。当然,可以通过token
属性阅读。
const useAuthenticationService = () => {
const [ token, setToken ] = useTokenStorage();
const login = async (email, password, remember) => {
const data = await ApiClient.post(`/api/auth`, {
email: email, password: password, remember: remember
});
setToken(data.token);
};
const logout = () => {
setToken('');
};
return { token, login, logout };
};
在组件中使用useAuthenticationService
钩子,您需要根据token
确定要呈现的内容,例如在App.js中
// App.js
const AppComponent = () => {
const { token } = useAuthenticationService();
return (
{ token && <Menu>Logged In</Menu> }
<Switch>
<PrivateRoute path="/dashboard" component={Dashboard} />
<Route path="/login" component={Login} />
<Route component={Error404} />
</Switch>
);
};
在需要更新令牌状态的地方使用login
和logout
函数。
// Login.js
const LoginComponent = () => {
const { login, logout } = useAuthenticationService();
async function handleSubmit(e) {
e.preventDefault();
try {
await login(email, password, remember);
history.push('/dashboard');
} catch (err) {
if(err.response.status === 401) {
setErrorMsg('Unauthorized access, please login again.');
}
}
}
render(
<form className={classes.form} noValidate onSubmit={handleSubmit}>
<TextField value={email} />
<TextField value={password} />
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
onChange={(e) => setRemember(e.target.value)}
value={remember}
/>
<Button type="submit">Sign In</Button>
</form>
);
}
token
现在应该与localStorage
保持同步,即使您浏览或刷新页面也是如此。