2017-02-23 3 views
0

Ich fühle mich total verwirrt, weil ich immer noch an diesem Thema von gestern arbeite und nichts hilft. Also, Problem: Ich habe To-Do-Liste. Jede Aufgabe hat einen Timer. Nur ein Timer kann gleichzeitig arbeiten, sodass der Benutzer nur eine Aufgabe gleichzeitig ausführen kann. Ich dachte, dass ich "Start" -Buttons bei anderen deaktivierten Aufgaben tun kann, wenn einer der Timer läuft, aber ich vermute, dass ich in meinem setState Fehler gemacht habe, weil alle Timer noch zusammen laufen = ( Ich lese Dokumentation aber es ist nicht für mich hilfreich. Außerdem habe ich Datei TodoTextInput, die diese Aufgaben erzeugen und ich dachte, vielleicht sollte ich meine Timer hier einfügen, aber es ist seltsam.Einmaliger Arbeitstimer

für vollständige Informationen, die ich hier zwei Dateien führen. Danke für jede Hilfe!

TodoItem(Ausgabe hier)

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(für alle Fälle)

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

So verstehe ich, dass das Problem ist, dass Sie alle Timer deaktiviert werden sollen, wenn Sie starten, habe ich Recht? Wo verwenden Sie die TodoItem-Komponente? –

+0

Ja, wenn ich bei einer Aufgabe auf "Start" klicke - sollte ich nicht die Möglichkeit haben, bei anderen Aufgaben auf "Start" zu klicken. Nur wenn ich bei dieser Aufgabe auf "Stop" klicke, kann ich eine andere Aufgabe und einen anderen Timer ausführen. TodoItem Komponente Ich importiere in Komponente MainSection - es ist der größte Teil der App. –

Antwort

0

Es gibt viele Möglichkeiten, dies zu tun. Sie könnten die ID des aktuell laufenden Timers im Zustand MainSection speichern und von einer TodoItem mit einer Callback-Funktion wie completeTodo ändern. Dann können Sie dieses Attribut des MainSection Zustand zu jedem TodoItem als Stütze und Check-in es zu senden, wenn es derjenige ist, der ausgeführt ist:

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

Der springende Punkt ist, dass Sie auf die MainSection kommunizieren müssen, die TodoItem ist läuft oder zumindest wenn TodoItem läuft. Soweit ich sehen kann, ist alles, was Sie über den Zustand des Timers speichern, lokal im Zustand der TodoItem, so dass die anderen TodoItems nicht wissen können, ob sie in der Lage sein sollen zu starten oder nicht.

Eine TODO-Liste ist almost a classic example of the Redux usage. Ich weiß nicht, ob Sie Redux in Ihre App einführen könnten, aber es ist definitiv ein großartiges Werkzeug, wenn es darum geht, einen globalen Zustand zu speichern.

+0

Ja, ich benutze Redux in meiner App und ich schreibe einfach "klassisches Beispiel" mit meinen Funktionen um. Also sowieso muss ich mit MainSection kommunizieren, ich habe Recht? –

+0

Entweder Sie kommunizieren mit MainSection oder Sie verwenden den Speicher von Redux. Wenn Sie beispielsweise die ID des aktuell laufenden Elements mit Redux speichern, müssen Sie sie nicht in MainSection speichern. –

Verwandte Themen