我正在用public class Test {
private int foo(){
System.out.println("Test");
return 1;
}
public static void main(String [] args) throws InterruptedException,
NoSuchMethodException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
Test innerClassObject = new Test();
Method method =
innerClassObject.getClass().getDeclaredMethod("foo",null);
method.setAccessible(true);
method.invoke(innerClassObject);
}
}
编码倒计时。
我正在使用Expo
,所以我的functional components
是通过React的state
钩子处理的。
useState
如果我按下let [state, setState] = useState({
secondsLeft: 25,
started: false,
});
,则会触发此功能:
Button
问题是每1000毫秒Expo会刷新应用程序而不是更新状态。
可以帮我吗?
答案 0 :(得分:0)
它更新状态,但是它使用陈旧状态来更新。一旦间隔开始,state
回调中的setInterval
变量就永远不会改变。
相反,请使用状态更新功能的设置器形式,因此您始终使用当时的状态:
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>