So right now I have a verifyScreen which users are sent to when they don't have a verified email. I have a setInterval function that runs every 5 seconds to see if the user has confirmed their email.
I also need to have a second setInterval for the resend email button in case a user has not received it. It counts down by 1 until it hits 0 and the user can resend an email.
If I have one or the other in my useEffect everything works fine. They also won't run together if the other is running so I need some help understanding how setInterval works behind the scenes and how I can fix my issue. Thank you.
const [emailTimer, setEmailTimer] = useState(0);
const [, setUser] = useAtom(userAtom);
useEffect(() => {
const userTimer = setInterval(async () => {
const refreshedUser = auth().currentUser;
console.log('checked user');
if (refreshedUser?.emailVerified) {
clearInterval(userTimer);
setUser(refreshedUser);
} else {
await auth().currentUser?.reload();
}
}, 5000);
const resendEmailTimer = setInterval(() => {
if (emailTimer <= 0) {
clearInterval(resendEmailTimer);
} else {
console.log('second subtracted');
setEmailTimer(emailTimer - 1);
}
}, 1000);
return () => {
clearInterval(userTimer);
clearInterval(resendEmailTimer);
};
}, [emailTimer]);
If you know the solution and can also explain to me the why behind all this, I would really appreciate that.
Edit, my component which sets the email timer:
<View style={{ paddingBottom: 10 }}>
<PrimaryButton
disabled={emailTimer > 0}
onPress={async () => {
setEmailTimer(60);
await handleSendEmailConfirmation();
}}>
<CustomText
text={emailTimer > 0 ? `${emailTimer}` : 'Resend email'}
color={theme.colors.white}
/>
</PrimaryButton>
</View>
<OutlinedButton
onPress={async () => {
await handleLogOut();
}}>
<CustomText text="Cancel" />
</OutlinedButton>
</View>
Edit:
What happens with the code right now:
The component renders, and the user interval runs every ~5 seconds. I click on the resend email button, which triggers the email timer every 1 second. While the email counter is going, the user counter pauses until it hits 0. Then the user counter resumes.
Console logs for more description:
Edit 2: Ok I managed to get both intervals working at the same time by moving the user interval outside of the useEffect. This way the email interval triggers when the state updates and it's added to the dependency array.
The one problem is the user interval that is outside of the useEffect sometimes triggers twice in the console. Not sure if that's because I'm running on a simulator or an error.
const [emailTimer, setEmailTimer] = useState(0);
const [, setUser] = useAtom(userAtom);
const userTimer = setInterval(async () => {
const refreshedUser = auth().currentUser;
console.log('checked user');
if (refreshedUser?.emailVerified) {
clearInterval(userTimer);
setUser(refreshedUser);
} else {
await auth().currentUser?.reload();
}
}, 10000);
useEffect(() => {
const resendEmailTimer = setInterval(() => {
if (emailTimer <= 0) {
clearInterval(resendEmailTimer);
} else {
console.log('second subtracted');
setEmailTimer(emailTimer - 1);
}
}, 1000);
return () => {
clearInterval(userTimer);
clearInterval(resendEmailTimer);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [emailTimer]);
