为了账号安全,请及时绑定邮箱和手机立即绑定

无法清除本机应用程序中的 setInterval

无法清除本机应用程序中的 setInterval

郎朗坤 2023-05-18 09:48:59
我有这个非常简单的应用程序,我试图在其中实现倒计时,Start并且Stop功能似乎运行良好但是当我按下时Stop,值seconds在视图中没有更新,这是期望的行为但是当我观察控制台日志时,它显示sec我猜不断变化的价值表明它setInterval仍在运行并且没有被清除。这是附带的代码:import React, { useState, useEffect } from "react";import {  StyleSheet,  Text,  View,  StatusBar,  TouchableOpacity,  Dimensions,} from "react-native";const screen = Dimensions.get("screen");export default function App() {  const [seconds, setSeconds] = useState(4);  const [start, setStartToggle] = useState(true);  let [fun, setFun] = useState(null);  const getRemaining = () => {    const minute = Math.floor(seconds / 60);    const second = seconds - minute * 60;    return formatTime(minute) + ":" + formatTime(second);  };  const formatTime = (time) => {    return ("0" + time).slice(-2);  };  const startTimer = () => {    setStartToggle(false);    console.log("StartTimer");    let sec = seconds;    setFun(      setInterval(() => {        console.log("akak:", sec);        if (sec <= 0) stopTimer();        setSeconds(sec--);      }, 1000)    );  };  const stopTimer = () => {    setStartToggle(true);    console.log("StopTimer");    clearInterval(fun);    setFun(null);  };  return (    <View style={styles.container}>      <StatusBar barStyle="light-content" />      <Text style={styles.timerText}>{getRemaining(seconds)}</Text>      {start ? (        <TouchableOpacity onPress={startTimer} style={styles.button}>          <Text style={styles.buttonText}>Start</Text>        </TouchableOpacity>      ) : (        <TouchableOpacity          onPress={stopTimer}          style={[styles.button, { borderColor: "orange" }]}        >          <Text style={styles.buttonText}>Stop</Text>        </TouchableOpacity>      )}    </View>  );}const styles = StyleSheet.create({  container: {    flex: 1,    backgroundColor: "#07121B",    alignItems: "center",    justifyContent: "center",  },应用行为:https://i.stack.imgur.com/fzdj6.gif 即使在点击停止后也会显示输出:https://i.stack.imgur.com/Ug0aJ.gif
查看完整描述

2 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

目前您使用useState挂钩来存储区间参考。在每次重新渲染组件时,App状态fun都会被重置,但不会是对间隔的完全相同的引用。


而是使用useRef钩子。它可以创建对间隔的引用,该间隔在重新渲染期间不会更改。这意味着引用属性中的值current将始终完全相同。


最重要的是,使用useEffect钩子来观察何时设置或取消设置运行状态,并根据该状态启动和停止计时器。


import React, { useState, useRef, useEffect } from 'react'


export default function App() {

  const [isRunning, setIsRunning] = useState(false);

  const funRef = useRef(null);


  const startTimer = () => {

    if (!isRunning) {

      setIsRunning(true);

    }

  };


  const stopTimer = () {

    if (isRunning && funRef.current !== null) {

      setIsRunning(false);

    }

  };


  useEffect(() => {

    if (isRunning) {

      funRef.current = setInterval(() => { // Save reference to interval.

        // ...

      }, 1000);

    } else {

      clearInterval(funRef.current); // Stop the interval.

    }

  }, [isRunning]);


  // ...

}


查看完整回答
反对 回复 2023-05-18
?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

在 useEffect 块中添加间隔计时器,并在每次开始更改时运行此块:


  useEffect(()=> {

        let timer = null;

    

        if(!start) {

          let sec = seconds;

          timer = setInterval(() => {

            console.log("akak:", sec);

            if (sec <= 0) clearInterval(timer);

            setSeconds(sec--);

          }, 1000);

        } else {

          clearInterval(timer);

       }

   }, [start]);



      const startTimer = () => {

        setStartToggle(false);

      };



      const stopTimer = () => {

        setStartToggle(true);

      };

另外,我建议您使用确切的剩余时间。Javascript 是单线程语言,这个间隔可能超过一秒


编辑:使用确切的时间。


  useEffect(() => {

    let timer = null;


    if (!start) {

      let sec = seconds;

      const startTime = Date.now();

      timer = setInterval(() => {

        const currentTime = Date.now();

        sec = sec - Math.floor((currentTime - startTime) / 1000);

        if (sec < 0) {

          clearInterval(timer);

          setSeconds(0);

        } else {

          setSeconds(sec);

        }

      }, 1000);

    }

  }, [start]);


查看完整回答
反对 回复 2023-05-18
  • 2 回答
  • 0 关注
  • 141 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信