如何一次就可以在两个数组元素上setState? [英] How can I setState on two array elements at once?

查看:101
本文介绍了如何一次就可以在两个数组元素上setState?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图建立一个定时演示应用程序。我使用 setInterval 来自动计数定时器,但是我的初始状态 timer 是一个有2个元素的数组,想在这两个计时器上统计下来。

I tried to build a Timer Demo App. I used setInterval to auto count down the timer, but my initial state timer is an array with 2 elements, and I want to count down on both timers together.

在我的代码中,只要我传递一个 id 参数到函数(如1或2),但是我想要一起倒数,我该怎么办?

In my code I just can count down one element if I pass an id argument into the function (like 1 or 2), but I want count down each together, how can I go about doing this?

这是我在CodePen中的演示

const timers = [
  {
    id: 1,
    time: 15,
  },
  {
    id: 2,
    time: 20,
  },
];
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state= {
      timers,
    }

  }
  componentDidMount(){
    setInterval(() => {
      this.countDown();
    }, 1000);
  }
  countDown(id){
    const foundTimer = this.state.timers.find(timer => timer.id === id);
    foundTimer.time = foundTimer.time - 1;
    this.setState({timers: this.state.timers});
  }

  renderTimers(){
    return(
     this.state.timers.map((timer) =>{
      console.log(timer);
      return(
        <div key = {timer.id} >
          <div>{timer.time}</div>
        </div>
      )
    })
    )
  }

  render() {

    return (
      <div>
        {this.renderTimers()}
      </div>
    );
  }
}


推荐答案

修改 this.state.timers ,其中包含将原始数组元素映射到新元素的 Array#map 。不要直接改变国家,这是所有邪恶的根源。例如:

Modify this.state.timers with something like Array#map that maps original array elements to new ones. Don't mutate state directly, it's the source of all evil. For example:

countDown() {
  this.setState(prevState => ({
    timers: prevState.timers.map(timer => ({
      ...timer,
      time: timer.time - 1
    }))
  }));
}

这将映射每个定时器到一个新的定时器,而不会突变状态,新定时器保留相同的属性(通过对象传播属性),除了它将每个定时器的时间属性更改为1当前时间。

This will map each of the timers to a new timer, without mutating state, where the new timers keep the same properties (via object spread properties) except it will change the time property of every timer to 1 less the current time.

如果对象传播属性不是在您的环境中支持,请使用 Object.assign

If object spread properties isn't supported in your environment, use Object.assign instead:

this.setState(prevState => ({
  timers: prevState.timers.map(timer =>
    Object.assign(
      {},
      timer,
      { time: timer.time - 1 }
    )
  )
}));

这将做同样的确切的事情,它将从定时器转换为空对象 {} (防止突变),然后覆盖时间属性并减少它。如果您的平台不支持对象传播属性,它只是一个更详细的版本。

This will do the same exact thing above, it will copy the properties from timer into an empty object {} (preventing mutation), then overriding the time property and decrementing it. It's just a more verbose version if your platform doesn't support object spread properties.

另外,考虑传递 timers as a prop ,而不是类之外的数组。限制变量到最窄范围。

Also, consider passing timers as a prop, not as an array outside the class. Restrict variables to their narrowest scope possible.

这篇关于如何一次就可以在两个数组元素上setState?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆