1 回答
TA贡献1873条经验 获得超9个赞
它更新状态,但它使用陈旧状态来执行此操作。一旦间隔开始,回调中的state变量将永远不会改变。setInterval
相反,请使用状态更新函数的 setter 形式,因此您始终使用当时的状态:
let onPressHandler = (): void => {
if(!state.started) {
setState({...state, started: true});
setInterval(()=> {
setState(currentState => {
const newState = {...currentState, secondsLeft: currentState.secondsLeft - 1};
console.log(newState.secondsLeft);
return newState;
});
}, 1000);
}
};
没有以下内容会更简洁console.log:
let onPressHandler = (): void => {
if(!state.started) {
setState({...state, started: true});
setInterval(()=> {
setState(currentState => {...currentState, secondsLeft: currentState.secondsLeft - 1});
}, 1000);
}
};
单独说明:如果您有彼此独立更新的状态项,最佳实践是为它们使用单独的状态变量。此外,由于它们在您的函数中是常量,因此最好将它们声明为const. 像这样:
const [secondsLeft, setSecondsLeft] = useState(25);
const [started, setStarted] = useState(false);
// ...
let onPressHandler = (): void => {
if(!started) {
setStarted(true);
setInterval(()=> {
setSecondsLeft(seconds => seconds - 1);
}, 1000);
}
};
此外,由于您不能完全依赖setInterval精确,我建议存储您的停止时间(“现在”加上 25 秒)并重新计算每次还剩多少秒:
let onPressHandler = (): void => {
const stopTime = Date.now() + (DURATION * 1000);
setStarted(true);
setSecondsLeft(DURATION);
const timer = setInterval(()=> {
const left = Math.round((stopTime - Date.now()) / 1000);
if (left <= 0) {
clearInterval(timer);
setStarted(false);
} else {
setSecondsLeft(left);
}
}, 1000);
};
现场示例(带有停止逻辑):
const {useState} = React;
const Example = () => {
const DURATION = 25; // seconds
const [started, setStarted] = useState(false);
const [secondsLeft, setSecondsLeft] = useState(0);
if (started) {
return <div>Seconds left: {secondsLeft}</div>;
}
let onPressHandler = ()/*: void*/ => {
const stopTime = Date.now() + (DURATION * 1000);
setStarted(true);
setSecondsLeft(DURATION);
const timer = setInterval(()=> {
const left = Math.round((stopTime - Date.now()) / 1000);
if (left <= 0) {
clearInterval(timer);
setStarted(false);
} else {
setSecondsLeft(left);
}
}, 1000);
};
return (
<input
type="button"
onClick={onPressHandler}
value="Start"
/>
);
};
ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
添加回答
举报