React 应用程序中的 setInterval

我在 React 公司还是个新手,但我一直在慢慢摸索,遇到了一些困扰我的问题。

我正在尝试在 React 中构建一个“计时器”组件,老实说,我不知道我这样做是否正确(或有效)。在下面的代码中,我将状态设置为返回一个对象 { currentCount: 10 },并且一直在玩弄 componentDidMountcomponentWillUnmountrender,我只能让状态从10“倒数”到9。

问题分两部分: 我哪里做错了?还有,是否有更有效的方法来使用 setTimeout (而不是使用 componentDidMountcomponentWillUnmount) ?

先谢谢你。

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;
280647 次浏览

我发现你的代码有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;

更新10秒倒计时使用 钩子(一个新的功能建议,让您使用状态和其他反应功能,而不需要编写一个类。他们目前在 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'));

谢谢@dotnetom,@greg-herbowicz

如果返回“ this. state is unDefinition”-bind timer 函数:

constructor(props){
super(props);
this.state = {currentCount: 10}
this.timer = this.timer.bind(this)
}

在 response 类中每秒更新状态。注意,my 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;

如果有人正在寻找一种实现 setInterval 的 React Hook 方法。Dan Abramov 在他的 博客节目里说过。如果你想要一个好的阅读主题,包括一个类的方法,检查出来。代码基本上是一个自定义 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

用反应钩管理 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)

简单的做法是将其添加到 window 变量中。

useEffect(() => {
window.interval23 = setInterval(
() => setState('something'),
2500
)
return () => {
clearInterval(window.interval23)
}
}, [])

但是要确保使用 window 变量创建的任何内容尽可能保持唯一性,因为如果该变量已经存在,则 window 变量可能会在库中中断。

如果您正在使用丹 Abramov Rel = “ nofollow noReferrer”> useInterval 钩子,并希望手动取消当前间隔,您只需要调用钩子再次传递 无效作为 推迟变量。

您可以在这里检查一个工作示例 https://codesandbox.io/s/useinterval-cancel-interval-dan-abramov-extended-oe45z?file=/src/index.js

您可以使用间隔来设置状态,方法是通过组合 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
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>;
};