React应用程序中的setInterval
setInterval in a React app
我在React还是个新手,但我一直在慢慢地努力,遇到了一些问题。
我正试图在React中构建一个"定时器"组件,老实说,我不知道我做得是否正确(或有效)。在下面的代码中,我将状态设置为返回对象{ currentCount: 10 }
,并且一直在玩componentDidMount
、componentWillUnmount
和render
,我只能将状态从10"倒计时"到9。
由两部分组成的问题:我做错了什么?还有,有没有更有效的方法来使用setTimeout(而不是使用componentDidMount
&componentWillUnmount
)?
提前谢谢。
import React from 'react';
var Clock = React.createClass({
getInitialState: function() {
return { currentCount: 10 };
},
componentDidMount: function() {
this.countdown = setInterval(this.timer, 1000);
},
componentWillUnmount: function() {
clearInterval(this.countdown);
},
timer: function() {
this.setState({ currentCount: 10 });
},
render: function() {
var displayCount = this.state.currentCount--;
return (
<section>
{displayCount}
</section>
);
}
});
module.exports = Clock;
我看到您的代码有4个问题:
- 在计时器方法中,您总是将当前计数设置为10
- 尝试在渲染方法中更新状态
- 您没有使用
setState
方法来实际更改状态 - 您没有将intervalId存储在该州
让我们试着解决这个问题:
componentDidMount: function() {
var intervalId = setInterval(this.timer, 1000);
// store intervalId in the state so it can be accessed later:
this.setState({intervalId: intervalId});
},
componentWillUnmount: function() {
// use intervalId from the state to clear the interval
clearInterval(this.state.intervalId);
},
timer: function() {
// setState method is used to update the state
this.setState({ currentCount: this.state.currentCount -1 });
},
render: function() {
// You do not need to decrease the value here
return (
<section>
{this.state.currentCount}
</section>
);
}
这将导致计时器从10减少到-N。如果你想要定时器减少到0,你可以使用稍微修改过的版本:
timer: function() {
var newCount = this.state.currentCount - 1;
if(newCount >= 0) {
this.setState({ currentCount: newCount });
} else {
clearInterval(this.state.intervalId);
}
},
使用class Clock extends Component
更新了10秒倒计时
import React, { Component } from 'react';
class Clock extends Component {
constructor(props){
super(props);
this.state = {currentCount: 10}
}
timer() {
this.setState({
currentCount: this.state.currentCount - 1
})
if(this.state.currentCount < 1) {
clearInterval(this.intervalId);
}
}
componentDidMount() {
this.intervalId = setInterval(this.timer.bind(this), 1000);
}
componentWillUnmount(){
clearInterval(this.intervalId);
}
render() {
return(
<div>{this.state.currentCount}</div>
);
}
}
module.exports = Clock;
使用Hooks更新了10秒倒计时(一个新的功能提案,允许您在不编写类的情况下使用状态和其他React功能。它们目前在React v16.7.0-alpha中)。
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
const Clock = () => {
const [currentCount, setCount] = useState(10);
const timer = () => setCount(currentCount - 1);
useEffect(
() => {
if (currentCount <= 0) {
return;
}
const id = setInterval(timer, 1000);
return () => clearInterval(id);
},
[currentCount]
);
return <div>{currentCount}</div>;
};
const App = () => <Clock />;
ReactDOM.render(<App />, document.getElementById('root'));
如果有人正在寻找React Hook方法来实现setInterval。丹·阿布拉莫夫在他的博客上谈到了这件事。如果你想好好读一读这门课,包括课堂教学法,可以看看它。基本上,代码是一个自定义Hook,它将setInterval转换为声明性的。
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
为了方便起见,还发布了CodeSandbox链接:https://codesandbox.io/s/105x531vkq
使用React挂钩管理setInterval:
const [seconds, setSeconds] = useState(0)
const interval = useRef(null)
useEffect(() => { if (seconds === 60) stopCounter() }, [seconds])
const startCounter = () => interval.current = setInterval(() => {
setSeconds(prevState => prevState + 1)
}, 1000)
const stopCounter = () => clearInterval(interval.current)
感谢@dotnetom,@greg herbowicz
如果返回"this.state is undefined"-绑定计时器函数:
constructor(props){
super(props);
this.state = {currentCount: 10}
this.timer = this.timer.bind(this)
}
如果您使用Dan AbramovuseInterval钩子,并且想要手动取消当前时间间隔,则只需要再次调用钩子,将null作为delay变量。
你可以在这里查看一个工作示例https://codesandbox.io/s/useinterval-cancel-interval-dan-abramov-extended-oe45z?file=/src/index.js
简单的做法是将其添加到窗口变量中。
useEffect(() => {
window.interval23 = setInterval(
() => setState('something'),
2500
)
return () => {
clearInterval(window.interval23)
}
}, [])
但是,请确保使用窗口变量创建的任何内容都尽可能保持其唯一性,因为如果该变量已经存在,则该窗口变量可能会在库中中断。
您可以使用interval来设置状态,方法是通过组合setTimeout和useEffect 创建我称之为假递归的递归
import {useEffect,useState} from 'react'
const [state,setState]=useState(0)
function Interval(){
setTimeout(()=>{
setState(state+1)
},2000)
}
useEffect(()=>Interval(),[state])
//this code runs repeatedly in interval of 2 seconds
在react类中每秒更新一次状态。请注意,我的index.js传递了一个返回当前时间的函数。
import React from "react";
class App extends React.Component {
constructor(props){
super(props)
this.state = {
time: this.props.time,
}
}
updateMe() {
setInterval(()=>{this.setState({time:this.state.time})},1000)
}
render(){
return (
<div className="container">
<h1>{this.state.time()}</h1>
<button onClick={() => this.updateMe()}>Get Time</button>
</div>
);
}
}
export default App;
import React, { useState, useEffect } from "react";
export const Count = () => {
const [currentCount, setCount] = useState(1);
const timer = () => setCount(currentCount + 1);
useEffect(
() => {
if (currentCount <= 0) {
return;
}
const id = setInterval(timer, 1000);
return () => clearInterval(id);
},
[currentCount]
);
console.log(currentCount)
return <div>Count : - {currentCount}</div>;
};
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- 如何使用UI Automation JavaScript Reference for iOS appium获取本机应用程
- 隔离每个线程/用户的setInterval
- JavaScript的setInterval可以阻止线程执行吗?
- $locationProvider html5mode导致“;无法获取“;刷新时出错-AngularJS Node应用程
- Cordova应用程序在安卓系统上运行,但线程似乎在ios上冻结了;“由于页面加载而重置插件”;
- setTimeOut() 或 setInterval() .4种方法应用相同的东西.哪个是最好的
- React应用程序中的setInterval
- 使用 .NET/C# 构建 Android 应用程序与使用 HTML/JavaScript 构建 Android 应用程
- 如何在Phonegap应用程序中创建一个简单的服务,以便在后台运行setInterval()
- SetInterval脚本应用于多个元素
- Delphi-can't在多线程应用程序中使用IWebBrowser2来抑制JavaScript错误对话框
- 如何保持网页显示期间JavaScript警报在Chrome &FireFox的一个VB ASP.. NET web应用程
- WinJS/Metro应用程序是单线程的吗?
- 如何判断setInterval是否是阻止应用退出的最后一件事
- JavaScript Windows 8应用程序setInterval()问题
- ionic应用程序中的计时器(setInterval)在后台运行一段时间后进入睡眠状态
- setInterval()函数是否表现得像一个线程?
- 从 setInterval 回调调用子例程会引发类型错误
- 在HTML5应用程序中下载后台数据到浏览器数据库- settimeout vs工作线程