如何解决私有路由react gatsby在能够检索用户信息以进行身份验证之前呈现
一旦我验证了用户的令牌,我就会将用户信息设置到 localStorage 中。 “isLoggedIn()”函数将检索用户信息以决定用户是否应该继续。
我遇到的问题是私有路由会在信息设置到localStorage之前先渲染,所以“isLoggedIn()”函数会先返回空的localStorage,我必须重新加载/刷新才能成功登录。
下面是我的代码片段,这个项目对我来说很重要,我必须尽快完成。我希望我能得到任何人的帮助。提前谢谢你们。
Index.js
const Index = () => {
return (
<div>
<Router>
<PrivateRoute path="/" component={Dashboard} />
<PrivateRoute path="/upload" component={Upload} />
<PrivateRoute path="/settings" component={Settings} />
<PrivateRoute path="/agents" component={Agents} />
<PrivateRoute path="/statistics" component={Statistics} />
<Login path="/login" />
</Router>
</div>
)
}
PrivateRoute.js
const PrivateRoute = ({ component: Component,location,...rest }) => {
if (!isLoggedIn() && location.pathname !== `/login`) {
navigate("/login")
return null
}
return <Component {...rest} />
}
Auth.js
export const isBrowser = () => typeof window !== "undefined"
export const getUser = () =>
isBrowser() && window.localStorage.getItem("user")
? JSON.parse(window.localStorage.getItem("user"))
: {}
export const setUser = user =>
window.localStorage.setItem("user",JSON.stringify(user))
export const handleLogin = async ({ email,password }) => {
const loginUser = { email,password };
const loginResponse = await Axios.post("http://localhost:5000/api/users/login",loginUser);
if (loginResponse) {
localStorage.setItem("auth-token",loginResponse.data.token);
let token = localStorage.getItem("auth-token");
if (token === null) {
localStorage.setItem("auth-token","");
token = "";
}
const tokenResponse = await Axios.post('http://localhost:5000/api/users/tokenIsValid',null,{ headers: { "x-auth-token": token } });
if (tokenResponse.data) {
const userRes = await Axios.get("http://localhost:5000/api/users/",{
headers: { "x-auth-token": token },});
return setUser({
username: userRes.data.displayName
})
}
}
return false
}
export const isLoggedIn = () => {
const user = getUser();
return !!user.username;
}
export const logout = callback => {
setUser({})
localStorage.setItem("auth-token","");
callback()
}
loginComponent.js
class loginComponent extends React.Component {
state = {
email: "",password: "",//sessionStay: "false"
}
handleSubmit = event => {
event.preventDefault()
handleLogin(this.state)
}
render() {
if (isLoggedIn()) {
if (typeof window !== "undefined") {
navigate(`/`)
}
}
return (
<div className="login-component-wrapper">
<img src={logo} className="login-logo" alt="logo" />
<h2>Agent Reporting Dashboard</h2>
<form className="login-form">
<div className="login-form-wrapper">
<label className="form-field-label" htmlFor="email">
Email:{" "}
</label>
<input
className="form-field"
name="email"
type="email"
onChange={e => {
this.setState({ email: e.target.value })
}}
onKeyPress={e => {
if (e.key === "Enter") {
this.handleSubmit(e)
navigate(`/`)
}
}}
value={this.state.email}
/>
<label className="form-field-label" htmlFor="password">
Password:{" "}
</label>
<input
className="form-field"
name="password"
type="password"
onChange={e => {
this.setState({ password: e.target.value })
}}
onKeyPress={e => {
if (e.key === "Enter") {
this.handleSubmit(e)
navigate(`/`)
}
}}
value={this.state.password}
/>
<input
type="checkbox"
name="session-stay"
onChange={e => {
this.setState({ sessionStay: e.target.value })
}}
value="true"
/>
<label className="form-field-label" htmlFor="session-stay">
Keep me logged in
</label>
<br />
<button
type="button"
className="login-button btn-primary"
onClick={event => {
this.handleSubmit(event)
navigate(`/`)
}}
>
Login
</button>
</div>
</form>
</div>
)
}
}
解决方法
磁盘操作(如设置 localStorage
)是异步的,因为它需要一些时间来执行,具体取决于 PC、网络等。
如果没有 CodeSandbox,很难猜测代码的行为方式,但对我来说,这似乎是一个异步问题。您可以尝试添加以下内容:
export const handleLogin = async ({ email,password }) => {
const loginUser = { email,password };
const loginResponse = await Axios.post("http://localhost:5000/api/users/login",loginUser);
if (loginResponse) {
await localStorage.setItem("auth-token",loginResponse.data.token);
let token = await localStorage.getItem("auth-token");
if (token === null) {
await localStorage.setItem("auth-token","");
token = "";
}
const tokenResponse = await Axios.post('http://localhost:5000/api/users/tokenIsValid',null,{ headers: { "x-auth-token": token } });
if (tokenResponse.data) {
const userRes = await Axios.get("http://localhost:5000/api/users/",{
headers: { "x-auth-token": token },});
return setUser({
username: userRes.data.displayName
})
}
}
return false
}
注意异步 await
函数中的 handleLogin
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。