我尝试构建一个Timer Demo App。我使用timer
来自动倒计时,但我的初始状态id
是一个包含2个元素的数组,我想在两个计时器上一起倒计时 。
在我的代码中,如果我将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>
);
}
}
参数传递给函数(例如1或2),我可以倒计时一个元素,但我想要将每个元素统计在一起,我该怎么做呢? / p>
{{1}}
答案 0 :(得分:4)
使用this.state.timers
修改Array#map
,将原始数组元素映射到新数组元素。不要直接改变国家,它是万恶之源。例如:
countDown() {
this.setState(prevState => ({
timers: prevState.timers.map(timer => ({
...timer,
time: timer.time - 1
}))
}));
}
这会将每个计时器映射到一个新的计时器,而不会改变状态,新的计时器保持相同的属性(通过object spread properties),除了它会将每个计时器的time
属性更改为减去当前时间。
如果您的环境不支持对象展开属性,请改用Object.assign
:
this.setState(prevState => ({
timers: prevState.timers.map(timer =>
Object.assign(
{},
timer,
{ time: timer.time - 1 }
)
)
}));
这将完成上述相同的操作,它会将属性从timer
复制到空对象{}
(防止变异),然后覆盖time
属性并递减它。如果您的平台不支持对象传播属性,它只是一个更详细的版本。
另外,请考虑将timers
作为 a prop 传递,而不是作为类外的数组。将变量限制在最窄范围内。
答案 1 :(得分:1)
好吧首先,改变状态并不是一个好主意,它可能导致意想不到的副作用,可能会给你带来真正的头痛。从不改变国家是一种好习惯。在不改变状态的情况下实现您想要的方法可以如下:
...
countDown() {
const newTimers = this.state.timers.map(t => Object.assign({}, t, { time: t.time - 1}));
this.setState({ timers: newTimers });
}
...