2016-11-09 3 views
4

Ich habe einen Timer mit setInterval() in einer React-Komponente und ich bin mir nicht sicher, was die Best Practices sind, um dieses Intervall in Bezug auf die Verwendung state zu starten und zu stoppen. Ich habe damit einige asynchrone Probleme.setInterval mit setState in React

Lassen Sie uns sagen, ich habe eine Reihe von Links in meinem React-Komponente, die den Rückruf machen und führen fein:

let links = [10, 50, 100, 500, 1000].map((num) => { 
    return(
    <Link key={num} onClick={(e) => this.switchNums(num)} to={`/somePath/${num}`}>{num}</Link> 
) 
}) 

Hier ist die switchNums() Funktion, wo ich es möchte einen vorhandenen Timer zurücksetzen:

switchNums(num){ 
    this.stopTimer() 
    this.reset(num) 
} 

Hier startTimer(), stopTimer() und reset():

startTimer(){ 
    if(!this.state.timerId){  
    let timerId = setInterval(()=>{ 
     let timer = this.state.timer + 1 
     this.setState({ 
     timer: timer, 
     timerId: timerId 
     }) 
    }, 1000) 
    } 
} 

stopTimer(){ 
    clearInterval(this.state.timerId)  
    this.setState({timerId:null}) 
} 

reset(size){ 
    this.setState({ 
    gameOver: false, 
    counter: 0, 
    correct: 0, 
    numbers: this.getRandomNumbers(size), 
    timer: 0 
    }, this.startTimer()) 
} 

Einer der Fehler ist das Klicken auf die Links führt schnell zu mehreren Intervallen trotz der if Bedingung in startTimer() auslösen. Ich vermute, das hat mit der asynchronen Natur von setState() zu tun. Ein weiterer Fehler (und ich denke damit zusammenhängend) ist, dass wenn ich langsam klicke, es das Intervall nur jedes zweite Mal startet.

Kann jemand etwas Licht darauf werfen? Oder was sie getan haben, um asynchrone Probleme zu umgehen, wobei setState in Verbindung mit setInterval verwendet wird (jeder gesetzte Zustand kann ein Versprechen zurückgeben?), Oder welche Lebenszyklus-Methoden würden für diese Art von Situation am besten sein?

Antwort

3

Ich denke, der größte Fehler hier ist, dass Sie state verwenden, um Ihr Intervall zu speichern. Obwohl technisch möglich, sehe ich keinen Grund, warum Sie das wirklich wollen.

Verwenden Sie stattdessen nur eine lokale Variable zu Ihrer Komponente:

startTimer(){ 
    if(!this.timerId){  
    this.timerId = setInterval(()=>{ 
     //your function 
    }, 1000); 
    } 
} 

stopTimer(){ 
    clearInterval(this.timerId); 
} 

Ich denke also nicht Sie die state überhaupt hier für Ihren Timer verwenden müssen. Sie haben einige andere allgemeine Fragen in Ihrem Beitrag, die sich auf state beziehen, und ich werde versuchen, diese unten zu beantworten. Denken Sie daran, dass sie bei der Lösung Ihres speziellen Problems irrelevant sind.


Was haben sie haben mit setState() asynchronen Probleme umgehen, getan?

Sie können einen Rückruf verwenden, um Code auszuführen, nachdem der state festgelegt wurde. Es gibt eine section of the official docs darüber; hier ist, was es sagt:

Der zweite Parameter ist eine optionale Callback-Funktion, die ausgeführt wird, sobald setState abgeschlossen ist und die Komponente neu gerendert wird.

setState(nextState, callback); 

Welche Lebenszyklus Methoden für diese Art von Situation am besten wäre?

Der gleiche Abschnitt des Dokuments weiter wie oben:

Generell empfehlen wir stattdessen componentDidUpdate() für eine solche Logik.

Wenn Sie mehr setState in Ihrer Funktion haben, und Sie mögen spezifischen Code nach einem bestimmten Ereignisse auszuführen, ich glaube, du bist in Ordnung, den Rückruf verwenden. Für allgemeinere Zwecke verwenden Sie die obige Lebenszyklusmethode.

+1

mein Gott, Sie können einfach Dinge in der Komponente selbst speichern ... Danke! werde es versuchen –

+0

Sicher Sache. Lass es mich wissen, wenn es funktioniert. – Chris

+0

Vielen Dank! das hat perfekt funktioniert. Das könnte also eine andere SO-Frage sein, aber welche anderen Dinge sind Eigenschaften der Komponente und nicht deren Zustand oder Requisiten? (neben Methoden) –

Verwandte Themen