clearInterval() 在 React Native 中不起作用 - 尝试从 class 转换为功能组件 - 计时器
clearInterval() not working in React Native - trying to convert from class to functional components - Timer
尝试在本机反应中制作秒表我有工作代码和class组件但是当尝试使用功能组件时clearInterval()
函数没有'没工作
来自 ReactNativeAcademy/Stopwatch 的源代码在此处修改之前 https://github.com/ReactNativeAcademy/Stopwatch/blob/master/App.js
我只需要一个没有圈数的基本计时器,只有 start/resume/stop /重置 按钮
零食 url 我的代码:https://snack.expo.io/@mansouriala/nervous-mixed-nuts
为了在基于 class 的组件中对其进行测试,您可以在功能函数下找到每个基于 class 的函数。
我不知道,但也许一个解决方案是将 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时,该代码仅在组件卸载时触发。
尝试在本机反应中制作秒表我有工作代码和class组件但是当尝试使用功能组件时clearInterval()
函数没有'没工作
来自 ReactNativeAcademy/Stopwatch 的源代码在此处修改之前 https://github.com/ReactNativeAcademy/Stopwatch/blob/master/App.js
我只需要一个没有圈数的基本计时器,只有 start/resume/stop /重置 按钮 零食 url 我的代码:https://snack.expo.io/@mansouriala/nervous-mixed-nuts 为了在基于 class 的组件中对其进行测试,您可以在功能函数下找到每个基于 class 的函数。
我不知道,但也许一个解决方案是将 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时,该代码仅在组件卸载时触发。