Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript setInterval刷新应用程序,而不是更新状态_Javascript_Typescript_React Native_Expo_Setinterval - Fatal编程技术网

Javascript setInterval刷新应用程序,而不是更新状态

Javascript setInterval刷新应用程序,而不是更新状态,javascript,typescript,react-native,expo,setinterval,Javascript,Typescript,React Native,Expo,Setinterval,我正在用Expo编码倒计时。 我使用的是功能组件,因此我的状态是通过React的useState钩子处理的 let [state, setState] = useState({ secondsLeft: 25, started: false, }); 如果我按下按钮它会触发此功能: let onPressHandler = (): void => { if(!state.started) { setState({...state, started:

我正在用
Expo
编码倒计时。 我使用的是
功能组件
,因此我的
状态
是通过React的
useState
钩子处理的

let [state, setState] = useState({
    secondsLeft: 25,
    started: false,
});
如果我按下
按钮
它会触发此功能:

let onPressHandler = (): void => {
    if(!state.started) {
        setState({...state, started: true});
        setInterval(()=> {
            setState({...state, secondsLeft: state.secondsLeft - 1});
            console.log(state.secondsLeft);
        }, 1000);
    }
}
问题是每1000毫秒Expo刷新一次应用程序,而不是更新状态。


你能帮我吗?

它更新状态,但它使用过时状态来更新。一旦间隔启动,
setInterval
回调中的
state
变量将永远不会更改

相反,请使用状态更新函数的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);
    }
};
没有
控制台,它更简洁。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);
};
let onPressHandler=():void=>{
const stopTime=Date.now()+(持续时间*1000);
设置开始(正确);
SetSecondLeft(持续时间);
常量计时器=设置间隔(()=>{
const left=Math.round((stopTime-Date.now())/1000);
如果(左){
常数持续时间=25;//秒
const[started,setStarted]=useState(false);
const[secondsLeft,setSecondsLeft]=useState(0);
如果(启动){
返回剩余秒数:{secondsLeft};
}
let onPressHandler=()/*:void*/=>{
const stopTime=Date.now()+(持续时间*1000);
设置开始(正确);
SetSecondLeft(持续时间);
常量计时器=设置间隔(()=>{
const left=Math.round((stopTime-Date.now())/1000);

如果(左)非常感谢您的非常清楚和详尽的解释!