Reputation: 63
I'm trying to use session storage to set some data, It doesn't work the first time, but works the second time.
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);
};
};
I'm expecting it to setState on initial submit, but it's okay setting it when I click submit again
Upvotes: 0
Views: 43
Reputation: 2280
useState
in React Hook
also is asynchronous
like this.setState
in React Component
.
So, you can try:
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);
};
};
Or if you still want use setUserData
, try apply useEffect
like:
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])
Upvotes: 0
Reputation: 15688
The setUserData()
method is asynchronous, which means there's nothing stopping the code written after it from executing before its own logic has completed. This is true for all state-updating methods.
What's likely happening is that the sessionStorage.setItem()
block runs before you've completely updated the state in the previous block. So there's nothing to save in localStorage the first-time around. But on subsequent attempts the state is updated with the token/user-info from the previous update.
There's a couple ways of resolving this:
1) Is to just update the local-storage with the variables you created instead of waiting for state to finish:
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) Employ useEffect()
to update localStorage when state-changes.
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);
};
};
Upvotes: 1