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

我有这个非常简单的应用程序,我试图在其中实现倒计时,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



郎朗坤
浏览 143回答 2
2回答

白衣非少年

目前您使用useState挂钩来存储区间参考。在每次重新渲染组件时,App状态fun都会被重置,但不会是对间隔的完全相同的引用。而是使用useRef钩子。它可以创建对间隔的引用,该间隔在重新渲染期间不会更改。这意味着引用属性中的值current将始终完全相同。最重要的是,使用useEffect钩子来观察何时设置或取消设置运行状态,并根据该状态启动和停止计时器。import React, { useState, useRef, useEffect } from 'react'export default function App() {&nbsp; const [isRunning, setIsRunning] = useState(false);&nbsp; const funRef = useRef(null);&nbsp; const startTimer = () => {&nbsp; &nbsp; if (!isRunning) {&nbsp; &nbsp; &nbsp; setIsRunning(true);&nbsp; &nbsp; }&nbsp; };&nbsp; const stopTimer = () {&nbsp; &nbsp; if (isRunning && funRef.current !== null) {&nbsp; &nbsp; &nbsp; setIsRunning(false);&nbsp; &nbsp; }&nbsp; };&nbsp; useEffect(() => {&nbsp; &nbsp; if (isRunning) {&nbsp; &nbsp; &nbsp; funRef.current = setInterval(() => { // Save reference to interval.&nbsp; &nbsp; &nbsp; &nbsp; // ...&nbsp; &nbsp; &nbsp; }, 1000);&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; clearInterval(funRef.current); // Stop the interval.&nbsp; &nbsp; }&nbsp; }, [isRunning]);&nbsp; // ...}

尚方宝剑之说

在 useEffect 块中添加间隔计时器,并在每次开始更改时运行此块:&nbsp; useEffect(()=> {&nbsp; &nbsp; &nbsp; &nbsp; let timer = null;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; if(!start) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let sec = seconds;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timer = setInterval(() => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log("akak:", sec);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sec <= 0) clearInterval(timer);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setSeconds(sec--);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, 1000);&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; clearInterval(timer);&nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp;}, [start]);&nbsp; &nbsp; &nbsp; const startTimer = () => {&nbsp; &nbsp; &nbsp; &nbsp; setStartToggle(false);&nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; const stopTimer = () => {&nbsp; &nbsp; &nbsp; &nbsp; setStartToggle(true);&nbsp; &nbsp; &nbsp; };另外,我建议您使用确切的剩余时间。Javascript 是单线程语言,这个间隔可能超过一秒编辑:使用确切的时间。&nbsp; useEffect(() => {&nbsp; &nbsp; let timer = null;&nbsp; &nbsp; if (!start) {&nbsp; &nbsp; &nbsp; let sec = seconds;&nbsp; &nbsp; &nbsp; const startTime = Date.now();&nbsp; &nbsp; &nbsp; timer = setInterval(() => {&nbsp; &nbsp; &nbsp; &nbsp; const currentTime = Date.now();&nbsp; &nbsp; &nbsp; &nbsp; sec = sec - Math.floor((currentTime - startTime) / 1000);&nbsp; &nbsp; &nbsp; &nbsp; if (sec < 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; clearInterval(timer);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setSeconds(0);&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setSeconds(sec);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; }, 1000);&nbsp; &nbsp; }&nbsp; }, [start]);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript