Good evening.
At the moment I am performing an assignment where I have encountered difficulty. I have a to-do list with the option of time-tracking tasks. The problem is that the user can run only one program at a time, i.e. he has to start the timer of only one task and at this time the buttons on the other timers are inactive to start.
Here is my code, I suspect that the problem is in setState, but I can not figure it out to the end. Timers appear, work, but continue to work simultaneously with each press on the start.
import React, { Component, PropTypes } from 'react' import classnames from 'classnames' import TodoTextInput from './TodoTextInput' export default class TodoItem extends Component { constructor(props) { super(props); this.state = { secondsStart: this.props.minSeconds, timerRunning: false } } static propTypes = { todo: PropTypes.object.isRequired, deleteTodo: PropTypes.func.isRequired, completeTodo: PropTypes.func.isRequired, } static defaultProps = { minSeconds: 0 } handleSave = (id, text) => { if (text.length === 0) { this.props.deleteTodo(id) } } handleStartClick = () => { if (!this.state.timerRunning) { this.incrementer = setInterval(() => { this.setState({ secondsStart: (this.state.secondsStart + 1) }); }, 1000) this.setState({ timerRunning: true, currentTodoId: this.props.todo.id, runningTodoId: this.props.todo.id }); } } getSeconds = () => { return ('0' + this.state.secondsStart % 60).slice(-2) } getMinutes = () => { return Math.floor((this.state.secondsStart / 60)%60) } getHoures = () => { return Math.floor((this.state.secondsStart / 3600)%24) } handleStopClick = () => { clearInterval(this.incrementer) this.setState({ timerRunning: false, currentTodoId: null, runningTodoId: null }); } render() { const { todo, completeTodo, deleteTodo} = this.props const element = this.state.todo ? ( <TodoTextInput text={todo.text} onSave={(text) => this.handleSave(todo.id, text)} /> ) : ( <div className="view"> <input className="toggle" type="checkbox" checked={todo.completed} onChange={() => completeTodo(todo.isRequired)} /> <label> {todo.text} </label> <div className="buttons"> <h6>{this.getHoures()}:{this.getMinutes()}:{this.getSeconds()}</h6> {(this.state.secondsStart === 0) ? <button className="timer-start" onClick={this.handleStartClick} disabled={this.state.timerRunning }>Start</button> : <button className="timer-stop" onClick={this.handleStopClick} disabled={!this.state.timerRunning && this.state.runningTodoId !== this.state.currentTodoId}>Stop</button> } </div> <button className="destroy" onClick={() => deleteTodo(todo.id)} /> </div> ) return ( <li className={classnames({ completed: todo.completed, })}> {element} </li> ) } } Also note that TodoItem has a parent, TodoTextInput, through which my Items are generated and I thought that maybe the timer needed to be generated from there, but still the solution is closer to me.
Thank you in advance!