2017-02-23 1 views
0

어제부터이 문제를 해결하고 도움이되지 않아서 혼란 스럽습니다. 문제는 다음과 같습니다.해야 할 일 목록이 있습니다. 모든 작업에는 타이머가 있습니다. 동시에 하나의 타이머 만 작동 할 수 있으므로 사용자는 동시에 하나의 작업 만 수행 할 수 있습니다. 타이머가 작동 중일 때 다른 작업에서 '시작'버튼을 사용할 수 없다고 생각했지만 모든 타이머가 여전히 함께 작동하기 때문에 setState에서 실수를했다고 가정합니다 = ( 설명서를 읽었지만 그렇지 않습니다. 또한 나에게 도움이. , 나는이 작업을 생성되는 파일 TodoTextInput을하고 난 여기 내 타이머를 붙여 넣기한다 어쩌면 생각하지만 이상하다. 모든 정보에 대한일회성 작업 타이머

내가 여기에 두 개의 파일을 둡니다. 이 주셔서 감사합니다 어떤 도움!

ToDoItem을(여기서 문제가)

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> 
    ) 
    } 
} 

TodoTextInput(단지 경우)

import React, { Component, PropTypes } from 'react' 
import classnames from 'classnames' 

export default class TodoTextInput extends Component { 
    static propTypes = { 
    onSave: PropTypes.func.isRequired, 
    text: PropTypes.string, 
    placeholder: PropTypes.string, 
    newTodo: PropTypes.bool 
    } 

    state = { 
    text: this.props.text || '' 
    } 

    handleSubmit = e => { 
    const text = e.target.value.trim() 
    if (e.which === 13) { 
     this.props.onSave(text) 
     if (this.props.newTodo) { 
     this.setState({ text: '' }) 
     } 
    } 
    } 

    handleChange = e => { 
    this.setState({ text: e.target.value }) 
    } 

    handleBlur = e => { 
    if (!this.props.newTodo) { 
     this.props.onSave(e.target.value) 
    } 
    } 

    render() { 
    return (
     <input className={ 
     classnames({ 
      'new-todo': this.props.newTodo 
     })} 
     type="text" 
     placeholder={this.props.placeholder} 
     autoFocus="true" 
     value={this.state.text} 
     onBlur={this.handleBlur} 
     onChange={this.handleChange} 
     onKeyDown={this.handleSubmit} /> 
    ) 
    } 
} 
+0

나는이 문제가 시작할 때 모든 타이머를 사용하지 못하도록한다는 것을 이해합니다. 맞습니까? TodoItem 컴포넌트를 어디에서 사용하고 있습니까? –

+0

예, 한 작업에서 '시작'을 클릭하면 다른 작업에서 '시작'을 클릭 할 수 없습니다. 이 작업에서 '중지'를 클릭 할 때만 다른 작업과 타이머를 실행할 수 있습니다. TodoItem 구성 요소 MainSection 구성 요소에서 가져옵니다. 앱의 가장 큰 부분입니다. –

답변

0

이 작업을 수행하는 방법에는 여러 가지가 있습니다. 은 현재 실행중인 타이머의 ID를 MainSection에 저장하고 에서 completeTodo과 같은 콜백 함수로 변경합니다.

render() { 
     const { todo, runningTodoId, startTodoTimer, completeTodo, deleteTodo} = this.props 
     let disable = runningTodoId == todo.id; 
    } 

요점은 당신이 TodoItemMainSection에 통신 할 필요가 있다는 것입니다 : 그것은 실행중인 사람이라면 그런 다음 소품으로 각 TodoItemMainSection 상태의이 속성을 전송하고 그것에서 확인하실 수 있습니다 실행 중이거나 적어도 실행 중일 경우 TodoItem입니다. 지금까지 내가 타이머의 상태에 관해 저장하고있는 것이 모두 TodoItem의 로컬에 있다는 것을 알 수 있으므로 다른 TodoItems은 시작할 수 있어야하는지 여부를 알 수 없습니다.

TODO 목록은 almost a classic example of the Redux usage입니다. Redux를 앱에 도입 할 수 있는지는 모르겠지만 글로벌 상태를 저장하는 데 있어서는 확실히 좋은 도구입니다.

+0

예, 저는 애플 리케이션에서 Redux를 사용하고 있으며 필자의 기능으로 "클래식 예제"를 다시 작성합니다. 어쨌든 MainSection과 통신해야합니다. 맞습니까? –

+0

MainSection과 comunicate하거나 Redux 저장소를 사용하십시오. 예를 들어 Redux로 현재 실행중인 Item의 ID를 저장하면 MainSection에 저장하지 않아도됩니다. –