javascript - clearInterval() 在 React Native 中不起作用 - 尝试从类转换为功能组件 - 计时器
问题描述
尝试在本机反应中制作秒表我有带有类组件的工作代码但是在尝试使用功能组件时该clearInterval()
功能不起作用
修改前来自 ReactNativeAcademy/Stopwatch 的源代码https://github.com/ReactNativeAcademy/Stopwatch/blob/master/App.js
我只需要一个没有圈数的基本计时器,我的代码只有开始/恢复/停止/重置按钮小吃网址:https ://snack.expo.io/@mansouriala/nervous-mixed-nuts 以便在基于类的测试组件,您可以在功能性功能下找到每个基于类的功能。
我不知道,但可能的一种解决方案是将 setInterval 包装在 useEffect 中,然后在启动时创建一个新的状态变量将其切换为 true,并且 useEffect 侦听该变量。
事不宜迟,代码如下:
import React, { Component, useEffect, useState } from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import moment from 'moment';
function Timer({ interval, style }) {
const pad = (n) => (n < 10 ? `0${n}` : n);
const duration = moment.duration(interval);
const centiseconds = Math.floor(duration.milliseconds() / 10);
return (
<View style={styles.timerContainer}>
<Text style={style}>{pad(duration.minutes())}:</Text>
<Text style={style}>{pad(duration.seconds())},</Text>
<Text style={style}>{pad(centiseconds)}</Text>
</View>
);
}
function RoundButton({ title, color, background, onPress }) {
return (
<TouchableOpacity onPress={onPress} style={[styles.button, { backgroundColor: background }]}>
<View style={styles.buttonBorder}>
<Text style={[styles.buttonTitle, { color }]}>{title}</Text>
</View>
</TouchableOpacity>
);
}
function ButtonsRow({ children }) {
return <View style={styles.buttonsRow}>{children}</View>;
}
// export default class App extends Component {
export default function App() {
const [timer, setTimer] = useState(0);
const [state, setState] = useState({
start: 0,
now: 0,
currentTime: 0,
});
// constructor(props) {
// super(props);
// this.state = {
// start: 0,
// now: 0,
// currentTime: 0,
// };
// }
useEffect(() => {
return () => {
clearInterval(timer);
};
}, []);
// componentWillUnmount() {
// clearInterval(this.timer);
// }
const startHandler = () => {
const now = new Date().getTime();
setState({
start: now,
now,
currentTime: 0,
});
setInterval(
setInterval(() => {
setState((prev) => ({ ...prev, now: new Date().getTime() }));
}, 100)
);
};
// startHandler = () => {
// const now = new Date().getTime();
// this.setState({
// start: now,
// now,
// currentTime: 0,
// });
// this.timer = setInterval(() => {
// this.setState({ now: new Date().getTime() });
// }, 100);
// };
const stopHandler = () => {
clearInterval(timer);
const { currentTime, now, start } = state;
setState((prev) => ({
// ...prev,
currentTime: currentTime + (now - start),
start: 0,
now: 0,
}));
};
// stopHandler = () => {
// clearInterval(this.timer);
// const { currentTime, now, start } = this.state;
// this.setState({
// currentTime: currentTime + now - start,
// start: 0,
// now: 0,
// });
// };
const resetHandler = () => {
setState({
currentTime: 0,
start: 0,
now: 0,
});
};
// resetHandler = () => {
// this.setState({
// currentTime: 0,
// start: 0,
// now: 0,
// });
// };
const resumeHandler = () => {
const now = new Date().getTime();
setState({
start: now,
now,
});
setTimer(
setInterval(() => {
setState((prev) => ({ ...prev, now: new Date().getTime() }));
}, 100)
);
};
// resumeHandler = () => {
// const now = new Date().getTime();
// this.setState({
// start: now,
// now,
// });
// this.timer = setInterval(() => {
// this.setState({ now: new Date().getTime() });
// }, 100);
// };
// render() {
const { now, start, currentTime } = state;
// const { now, start, currentTime } = this.state;
return (
<View style={styles.container}>
<Timer interval={currentTime + (now - start)} style={styles.timer} />
<ButtonsRow>
<RoundButton title={'Start'} color={'#50D167'} background={'#1B361F'} onPress={startHandler} />
<RoundButton title={'Stop'} color={'#E33935'} background={'#3C1715'} onPress={stopHandler} />
<RoundButton title={'Reset'} color={'#FFFFFF'} background={'#3D3D3D'} onPress={resetHandler} />
<RoundButton title={'Resume'} color={'#50D167'} background={'#1B361F'} onPress={resumeHandler} />
</ButtonsRow>
</View>
);
}
// }
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0D0D0D',
alignItems: 'center',
paddingTop: 130,
paddingHorizontal: 20,
},
timer: {
color: '#FFFFFF',
fontSize: 76,
fontWeight: '200',
width: 110,
},
button: {
width: 80,
height: 80,
borderRadius: 40,
justifyContent: 'center',
alignItems: 'center',
},
buttonTitle: {
fontSize: 18,
},
buttonBorder: {
width: 76,
height: 76,
borderRadius: 38,
borderWidth: 1,
justifyContent: 'center',
alignItems: 'center',
},
buttonsRow: {
flexDirection: 'row',
alignSelf: 'stretch',
justifyContent: 'space-between',
marginTop: 80,
marginBottom: 30,
},
timerContainer: {
flexDirection: 'row',
},
});
解决方案
试试看:
useEffect(() => {
clearInterval(timer);
}, []);
在 useEffect 中使用return时,代码仅在组件卸载时触发。
推荐阅读
- angularjs - Angularjs 应用程序 - 来自 JSON 的用户输入和输出
- excel - Word 宏:查找关键字并将句子提取到 Excel
- xpath - XPath:ax following-sibling 不够准确
- java - 输出中跳过的用户输入
- regex - 正则表达式匹配带或不带查询参数的无扩展 url
- c# - 从字典中获取特定值
- aem - HTML中的珊瑚UI元素
- c++ - 如何在 MFC 窗口中输出 cv::Mat
- javascript - 如何将笔画属性添加到绘制的元素?
- python - 使用 Selenium 单击“下一步”按钮,直到解析所有页面:Python3