Countdown gets stuck at 1sec 'react-native-background-timer'

28 Views Asked by At

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>
  );
} ```
0

There are 0 best solutions below