gpt4 book ai didi

javascript - 无法清除 react native 应用程序中的setInterval

转载 作者:行者123 更新时间:2023-12-03 08:34:26 27 4
gpt4 key购买 nike

我有一个非常简单的应用程序,我试图在其中实现倒计时,StartStop 功能似乎工作正常,但是当我按 Stop,秒的值没有在 View 中更新,这是期望的行为,但是当我观察控制台日志时,它显示秒的值不断变化,我猜测显示 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",
},
button: {
borderWidth: 10,
borderColor: "#89aaff",
width: screen.width / 2,
height: screen.width / 2,
borderRadius: screen.width / 2,
justifyContent: "center",
alignItems: "center",
},
buttonText: {
fontSize: 40,
color: "#89aaff",
fontWeight: "bold",
},

timerText: {
fontSize: 90,
color: "#89aaff",
fontWeight: "bold",
marginBottom: 20,
},
});

应用程序行为:

enter image description here

即使在停止后仍显示输出:

enter image description here

感谢 Emily Zuurbierlissettdm 的回答,我的代码现在可以运行了。

工作代码:

// import { StatusBar } from "expo-status-bar";
import React, { useState, useEffect, useRef } 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(11);
const funRef = useRef(null);
const [start, setStartToggle] = useState(true);

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);
};
let sec = seconds;
useEffect(() => {
// let timer = null;

if (!start) {
let sec = seconds;
funRef.current = setInterval(() => {
console.log("Seconds remaining:", sec);
if (sec <= 0) {
clearInterval(funRef.current);
setStartToggle(true);
}
setSeconds(sec--);
}, 1000);
} else {
clearInterval(funRef.current);
}
}, [start]);

const startTimer = () => {
setSeconds(sec);
setStartToggle(false);
};

const stopTimer = () => {
setSeconds(sec);
setStartToggle(true);
};

return (
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<Text
style={
seconds ? styles.timerText : [styles.timerText, { color: "red" }]
}
>
{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",
},
button: {
borderWidth: 10,
borderColor: "#89aaff",
width: screen.width / 2,
height: screen.width / 2,
borderRadius: screen.width / 2,
justifyContent: "center",
alignItems: "center",
},
buttonText: {
fontSize: 40,
color: "#89aaff",
fontWeight: "bold",
},

timerText: {
fontSize: 90,
color: "#89aaff",
fontWeight: "bold",
marginBottom: 20,
},
});

最佳答案

当前您使用 useState Hook 来存储间隔引用。每次重新渲染 App 组件时,fun 状态都会重置,但不会是对间隔的完全相同的引用。

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

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

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]);

// ...
}

关于javascript - 无法清除 react native 应用程序中的setInterval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64371873/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com