[英]How can I setState on just one array element at once?
我是ReactJS和javascript的初学者
我有一个问题,关于如何一次在两个数组元素上设置状态?
在那个问题上,响应者告诉我无论如何都不要改变状态。
但是我还有另一个问题,如果我想通过使用clearInterval()
停止倒数计时器,当计时器到达0时。
在我对codePen Timer Demo 2的新尝试中,
我使用find()
方法找到时间为0的元素,并使用clearInterval
停止递减计数,但是如果一个元素的时间到达0而另一个没有到达,则所有元素都停止了。
我该如何解决?
const timers = [
{
id: 1,
time: 5,
timeIsUp: false,
},
{
id: 2,
time: 10,
timeIsUp: false,
},
];
class Clock extends React.Component {
constructor(props) {
super(props);
this.state= {
timers,
}
this.time_controller = 0;
}
componentDidMount(){
this.time_controller = setInterval(() =>{
this.countDown();
}, 1000)
}
countDown(){
const foundTimers = this.state.timers.map(timer => ({
...timer,
time: timer.time-1
}));
this.setState({timers: foundTimers});
const foundTimer = foundTimers.find(timer => timer.time === 0 );
if(!!foundTimer){
clearInterval(this.time_controller);
}
}
renderTimers(){
return(
this.state.timers.map((timer) =>{
return(
<div key = {timer.id} >
<div>{timer.time}</div>
</div>
)
})
)
}
render() {
return (
<div>
{this.renderTimers()}
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
这与状态管理无关,它的逻辑很简单:
旁注: timeIsUp
标志实际上没有任何原因,在吗? time === 0
表示时间到了,不是吗? 复制状态打开了漏洞的大门,您可以在一个地方而不是其他地方进行更新。
遵循这些原则,但细节并不像概念那么重要:
countDown() {
let updated = false;
let keepTicking = false;
const updatedTimers = this.state.timers.map(timer => {
// Note that if we don't modify `timer`, we return it for reuse
if (timer.time > 0) {
timer = {...timer, time: timer.time - 1};
updated = true;
keepTicking = timer.time > 0;
}
return timer;
});
if (updated) {
// We changed somthing, update
this.setState({timers: updatedTimers});
}
if (this.time_controller !== 0 && !keepTicking) {
// No more active timers, stop ticking
clearInterval(this.time_controller);
this.time_controller = 0;
}
}
请注意,清除计时器时会清除计时器句柄,因此我们知道计时器是否正在运行。
请注意,在这个例子中,我采取的务实的态度map
有副作用的回调(设置updated
和keepTicking
标志)。 我没有像这样的局部副作用的问题,但是有很大的动作可以解决。
非副作用版本将至少部分循环计时器一次以上:
countDown() {
const timers = this.state.timers;
// Need to update?
if (timers.find(t => t.time > 0)) {
const updatedTimers = timers.map(timer => (
// If we don't change a timer, we can reuse it
timer.time === 0 ? timer : {...timer, time: timer.time - 1}
);
this.setState({timers: updatedTimers});
}
// Done ticking?
if (this.time_controller !== 0 && updatedTimers.every(t => t.time === 0)) {
clearInterval(this.time_controller);
this.time_controller = 0;
}
}
请注意代码如何更简洁(因为我们仅在需要时才表达我们正在做的每件事),但效率却较低(我们可能必须努力工作才能找到需要更新的计时器,并让我们保持滴答作响) 。 在90%的时间内,效率并不重要, timers
长度将少于几千个条目。 所以有一个论点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.