Home > OS >  AppState Always firing on Timer
AppState Always firing on Timer

Time:10-06

I am building a Timer to run in the background

I am Using React Native and Expo to build the app

Now the timer I am using I am trying to let it "run" in the background

To do this I am using AppState and a event listner, taking the Start Time, and the elapsed Time (Elabsed while the app is minimized) And then recalculating the Time elapsed and adding that to the timer

In the Timer There are start, pause, reset and done buttons

Want I am not getting to work is that the elapsed time must not get set into the setstate if the pause button is clicked, and no matter how many IFs I put in there, the Time always gets changed

  const appState = useRef(AppState.currentState);
const [timerOn, setTimerOn] = useState(false);
const [time, setTime] = useState(0);
const [Paused,isPaused] = useState("");




const getElapsedTime = async () => {
  try {
    
    const startTime = await AsyncStorage.getItem("@start_time");
    const now = new Date();
    return differenceInSeconds(now, Date.parse(startTime));
    
  
  } catch (err) {
    
    console.warn(err);
  }
};


const recordStartTime = async () => {
  try {
    const now = new Date()
    await AsyncStorage.setItem("@start_time", now.toISOString());
  } catch (err) {
    console.warn(err);
  }
};


useEffect(() => {
  
 Timer()


}, []);

function Timer(){

  if(Paused == "no"){
   
  AppState.addEventListener("change", handleAppStateChange);
   return () => AppState.removeEventListener("change", handleAppStateChange);
  
  
  
  
  }
  else{
    console.log("eVENT lISTNER")
  }



}```

const handleAppStateChange = async (nextAppState) => {

  if (appState.current.match(/inactive|background/) &&
    nextAppState == "active" && Paused == "no") {
      // We just became active again: recalculate elapsed time based 
    // on what we stored in AsyncStorage when we started.
    const elapsed = await getElapsedTime();
    // Update the elapsed seconds state
//THE BELOW STATE IS UPDATED TO "ELAPSED" EVENTHOUGH IN THE IF STATEMENT ABOVE SAYS "PAUSED = NO" 
    setTime(elapsed);
        }
        else{
          console.log("YES")
        }
      
  appState.current = nextAppState;
};

  useEffect(() => {
    let interval = null;
  
    if (timerOn) {
      interval = setInterval(() => {
        setTime((prevTime) => prevTime   1);
      }, 1000);
    } else if (!timerOn) {
      clearInterval(interval);
    }
  
    return () => clearInterval(interval);
  }, [timerOn]);

  let MyHour = ("0"   Math.floor((time / 3600))).slice(-2);
let MyMinutes =("0"   Math.floor((time / 60) % 60)).slice(-2);
let MySeconds = ("0"   ((time % 60))).slice(-2);

function TimerBtn(){
 isPaused("no")
  setTimerOn(true)
  recordStartTime()
}


function PauseBtn(){
isPaused("yes")
  setTimerOn(false)

}
function ResetBtn(){

  setTimerOn(false)
  setTime(0)
}
function DoneBtn(){


}

CodePudding user response:

Your problem is probably that you cannot access the current state of Paused inside a listener. Read this answer here for a detailed explanation To work around, use a reference instead (useRef).

const [Paused,isPaused] = useState("");

to

const isPaused = useRef(true); // use booleans instead of "yed"/"no"

keep in mind to read and write to references you have to append '.current' to the reference, e.g:

isPaused.current = true;
// or
if (isPaused.current) {...} 
  • Related