2016-08-12 2 views
0

Ich benutze moment.duration, um einen Countdown-Timer in einer react.js-App zu erstellen, wobei die ursprüngliche Countdown-Zeit von einem API-Aufruf in componentDidMount abgerufen wird.Reagieren mit Moment.duration: Komponente erneut rendern, wenn die Dauer 0 erreicht

So viel funktioniert gut - ich möchte, sobald meine Dauer 0 ist (sobald ein Ereignis beginnt), die Komponente erneut rendern (die wiederum eine neue Zeit ziehen wird als Countdown dienen, als die JSON wird mit den kommenden Ereignissen aktualisiert.

Dies scheint, wie es mit React sollte einfach sein, da ich im Grunde der Komponente jedes Mal neu machen will ich die Dauer erreichen, oder wenn der Countdown = 0.

Hier ist der Teil meines Codes machen:

render: function() { 
    UpcomingMenu = this.state.upcomingList || []; 
    var currentTime = Math.round(new Date().getTime()/1000); 
    // current system time in seconds 
    console.log(currentTime); 

    return (
     <div> 
     <span>Upcoming LIVE Event: </span> 
     {UpcomingMenu.map(function(el, i){ 

     if (el.eventStart > currentTime) { 
      while (i < 1) { //i hate while loops. find a better way... 
      var diffTime = el.eventStart - currentTime; 
      var duration = moment.duration(diffTime*1000, 'milliseconds'); 
      var interval = 1000; 
      if (typeof el.eventStart !== 'undefined') { //to prevent render twice error. i'm sure there's a better way around this. 
       setInterval(function(){ 
       duration = moment.duration(duration - interval, 'milliseconds'); 
        $('.countdown').text(duration.days() + "d " + duration.hours() + "h " + duration.minutes() + "m " + duration.seconds() + "s") 
       }, interval); 
      //re-render component? 
      }; 

      var eventDetailsURL = decodeURIComponent(el.eventDetailsURL); 
      var eventLiveURL = decodeURIComponent(el.eventLiveURL); 
       return <span key={i}> 
        <strong><a target="_blank" href={eventDetailsURL}>{el.eventTitle}</a></strong> 
        <p> 
        <span className="countdown"></span>      
        </p> 

       </span> 
      }; 

       };    
      })} 


      </div>   
    ); 
    } 
    }); 
+0

, wenn die Dauer 0 ist, aktualisieren Sie den Zustand mit mehr Daten. Dies wird für das Rendern sorgen. – vijayst

+0

@Vijay Danke-- Ja, aber die Dauer wird nur bei Pagelad eingestellt. – dilettante

+0

@dilettante Auf der Hauptseite von reactjs gibt es ein Timer-basiertes Beispiel: https://facebook.github.io/react/index.html. Wenn du es noch nicht getan hast, sieh es dir an. Im Wesentlichen möchten Sie etwas wie "tick" -Funktion in dort tun und setzen Sie den Zustand (oder den Zustand zurücksetzen) entsprechend, die für das erneute Rendern der Komponente sorgen wird. – KumarM

Antwort

0

es ist keine gute Praxis, setInterval in Ihre render() Funktion zu setzen. Render sollte rein sein und hat keine Nebenwirkung. Sie können Ihr Intervall-Setup immer auf eine andere Lebenszyklusmethode stellen, z. componentDidMount oder componentWillReceiveProps

class Timer extends React.Component { 
    static propTypes = { 
    eventStartTime: React.PropTypes.Date.isRequired 
    }; 

    // every logic is here 
    updateTimer =() => { 
    // clean up previous timer 
    clearTimeout(this.timer); 

    const millisecondsAhead = this.props.eventStartTime - Date.now(); 
    const eventStarted = millisecondsAhead < 0; 

    // calling setState will make your component re-render 
    this.setState({ 
     eventStarted: eventStarted 
    }); 

    if (!eventStarted) { 
     this.timer = setTimeout(this.updateTimer, 1000); 
    } 
    } 

    constructor(props) { 
    this.state = { 
     eventStarted: false 
    }; 

    this.updateTimer(); 
    } 

    componentWillReceiveProps(nextProps) { 
    if (nextProps.eventStartTime !== this.props.eventStartTime) { 
     this.updateTimer(); 
    } 
    } 

    render() { 
    const { eventStarted } = this.state; 
    const millisecondsAhead = this.props.eventStartTime - Date.now(); 
    /* 
    * render according to eventStarted and millisecondsAhead 
    */ 
    } 
} 
+0

Besser setInterval anstelle von setTimeout zu verwenden. vielleicht, eine andere Methode namens initTimer, um Aktionen zu bereinigen und den Timer zu starten. – vijayst

+1

@tungv als eine gute Praxis Sie möchten den Konstruktor als das erste Ding in Ihrer Klasse haben. Es wird sonst nur verwirrend. – KumarM

+0

Hallo, SetInterval hat meistens funktioniert, und ich habe den Konstruktor früher in der Klassendefinition verschoben. Danke euch beiden. – dilettante

Verwandte Themen