I am trying to implement a countdown to prevent users to login into my app for 1min after they failed login in 5 times in a row. This countdown starts at 60sec to 00sec and should keep running even if the user leaves the screen or the app. So far, nothing wrong, but then once I reached 01sec, it stays stuck. Because of this, the button that enables login remains disabled and I can't find why the countdown doesn't just stops. Any idea? Thanks in advance :)
export default function LoginResident() {
[... other variables]
const [failedAttempts, setFailedAttempts] = useState(1);
const [secondsLeft, setSecondsLeft] = useState(3601);
const [timerOn, setTimerOn] = useState(false);
const startTimer = () => {
BackgroundTimer.runBackgroundTimer(() => {
setSecondsLeft(secs => {
if (secs > 0) return secs - 1;
else return 0;
});
}, 1000);
};
// Checks if secondsLeft = 0 and stop timer
useEffect(() => {
if (secondsLeft === 0) BackgroundTimer.stopBackgroundTimer();
}, [secondsLeft]);
// Runs when timerOn value changes to start or stop timer
useEffect(() => {
if (timerOn) startTimer();
else BackgroundTimer.stopBackgroundTimer();
return () => {
BackgroundTimer.stopBackgroundTimer();
};
}, [timerOn]);
// to format the rendered countdown
const clockify = () => {
let seconds = Math.floor(secondsLeft % 60);
let displaySecs = seconds < 10 ? `0${seconds}` : seconds;
return {
displaySecs,
};
};
async function onSignInPressed() {
try {
const response = await loginResident(email, password);
if (response.statusCode === 400) {
if (response.reason === 'INVALID_LOGIN_CREDENTIALS') {
setError('');
setFailedAttempts(failedAttempts + 1);
AsyncStorage.setItem(
'failedAttempts',
JSON.stringify(failedAttempts),
);
if (failedAttempts >= 5) {
startTimer();
}
setTimeout(async () => {
await AsyncStorage.removeItem('failedAttempts');
await AsyncStorage.setItem('failedAttempts', '1');
await AsyncStorage.removeItem('countdownTime');
}, 60000);
return;
}
} else if (response.reason === 'NO_PASSWORD') {
setError('');
}
return;
} else {
setFailedAttempts(1);
const {
response: {
userReturn: [userInfos],
token: tokenSaved,
},
} = response;
setUser({
[...]
});
toggleRememberMe(isSelected, tokenSaved);
hideMessage();
navigation.navigate('Buildings');
setError('');
setSelection(false);
setEmail('');
setPassword('');
setErrorStyle(false);
}
} catch (e) {
setErrorStyle(true);
}
}
return (
<SafeAreaView style={styles.root}>
[...]
</View>
<Text style={styles.errorMsg}>{error}</Text>
{secondsLeft > 0 && ( // this should be gone once the countdown reaches 0
<Text style={styles.errorMsg}>
Prochaine tentative possible dans: {clockify().displaySecs} sec.
</Text>
)}
<View style={styles.viewCustomButtonSeConnecter}>
<CustomButton
text="SE CONNECTER"
onPress={onSignInPressed}
type="PRIMARY"
disabled={secondsLeft > 0}
/>
</View>
</View>
</SafeAreaView>
);
} ```