我正在尝试使用会话存储来设置一些数据,它第一次不起作用,但第二次有效。
const login = async (email, password) => {
try {
const user = await loginUser({
variables: {
email,
password
}
});
const { userId, token, expiresIn } = user.data.loginUser;
setUserData({
token: token,
userId: userId,
expiresIn: expiresIn
})
sessionStorage.setItem('interdevs-data', JSON.stringify({
"token": userData.token,
"userId": userData.userId,
"expiresIn": userData.expiresIn
}));
} catch(err) {
setLoginErr(err);
};
};
我希望它在初始提交时设置状态,但是当我再次单击提交时可以设置它
setUserData()
方法是异步的,这意味着在它自己的逻辑完成之前,没有什么可以阻止在它之后编写的代码执行。这适用于所有状态更新方法。
可能发生的情况是,sessionStorage.setItem()
块在您完全更新上一个块中的状态之前运行。因此,第一次在本地存储中没有什么可以保存的。但在后续尝试中,状态将使用上次更新中的令牌/用户信息进行更新。
有几种方法可以解决此问题:
1( 只是使用您创建的变量更新本地存储,而不是等待状态完成:
const login = async (email, password) => {
try {
const user = await loginUser({
variables: {
email,
password
}
});
const { userId, token, expiresIn } = user.data.loginUser;
setUserData({
token: token,
userId: userId,
expiresIn: expiresIn
})
sessionStorage.setItem('interdevs-data', JSON.stringify({
"token": token,
"userId": userId,
"expiresIn": expiresIn
}));
} catch(err) {
setLoginErr(err);
};
};
2( 使用useEffect()
在状态更改时更新本地存储。
useEffect(() => {
sessionStorage.setItem('interdevs-data', JSON.stringify({
"token": userData.token,
"userId": userData.userId,
"expiresIn": userData.expiresIn
}));
}, [user]) //swap user with whatever you called your state
const login = async (email, password) => {
try {
const user = await loginUser({
variables: {
email,
password
}
});
const { userId, token, expiresIn } = user.data.loginUser;
setUserData({
token: token,
userId: userId,
expiresIn: expiresIn
})
} catch(err) {
setLoginErr(err);
};
};
React Hook
中的useState
也asynchronous
像React Component
中的this.setState
。
因此,您可以尝试:
const login = async (email, password) => {
try {
const user = await loginUser({
variables: {
email,
password
}
});
const { userId, token, expiresIn } = user.data.loginUser;
// setUserData({
// token: token,
// userId: userId,
// expiresIn: expiresIn
// })
// userData here not yet updated
sessionStorage.setItem('interdevs-data', JSON.stringify({
"token": token,
"userId": userId,
"expiresIn": expiresIn
}));
// In your case, you can direct access to user.data.loginUser. Don't need use setUserData
} catch(err) {
setLoginErr(err);
};
};
或者,如果您仍然想使用setUserData
,请尝试应用如下useEffect
:
const login = async (email, password) => {
try {
const user = await loginUser({
variables: {
email,
password
}
});
const { userId, token, expiresIn } = user.data.loginUser;
setUserData({
token: token,
userId: userId,
expiresIn: expiresIn
})
} catch(err) {
setLoginErr(err);
};
};
useEffect(() => {
sessionStorage.setItem('interdevs-data', JSON.stringify({
"token": userData.token,
"userId": userData.userId,
"expiresIn": userData.expiresIn
}));
}, [userData])