title: SetTimeout runs twice, only if the component is reconstructed
body: <p>So this is very weird. First of all here's part of my code responsible for the timeouts:</p>
  
  <pre><code>constructor(props) {
      super(props);
      this.state = {
          assignments: [],
          answers: [],
          uploadedFile: '',
          showTimeoutModal: false,
      };
      this.onImageDrop = this.onImageDrop.bind(this);
      this.startCountDown = this.startCountDown.bind(this);
      this.handleTimeoutButtonClick = this.handleTimeoutButtonClick.bind(this);
  }
  
  
  componentDidMount() {
      clearTimeout(this.state.timer);
      firebase.database().ref('Works').child(this.props.assignmentId).once('value', () =&gt; {
          // var startTime = r.val().acceptedDate.time;
          var startTime = Time.generate().time; //todo change to db specific time
          var waitingTime = Time.makeMinutes(5);
          var endTime = Time.generate().time + waitingTime;
          this.setState({timer: this.startCountDown(startTime, endTime)});
      }).catch(e =&gt; console.log(e));
  }
  
  componentWillUnmount() {
      clearTimeout(this.state.timer);
  }
  
  startCountDown(startTime, endTime) {
      var timeout = setTimeout(function () {
          var now = startTime;
          console.log(endTime - now);
          if (now &gt;= endTime) {
              clearTimeout(timeout);
              console.log(true);
              this.setState({showTimeoutModal: true});
          } else {
              now = Time.generate().time;
              this.setState({timer: this.startCountDown(now, endTime)});
          }
      }.bind(this), 1000);
      return timeout;
  }
  
  handleTimeoutButtonClick() {
      var startTime = Time.generate().time;
      var waitingTime = Time.makeMinutes(0.15);
      var endTime = Time.generate().time + waitingTime;
  
      this.setState({showTimeoutModal: false, timer: this.startCountDown(startTime, endTime)});
  }
  </code></pre>
  
  <p>The way my project works is: A user picks a task to solve. I don't fully understand React yet so I don't fully know what's going on in the background. But the fact is, when I construct the component for the first time, all goes well. When I leave the component to a different route, all works as well. But if I recreate this component it all breaks.</p>
  
  <p>Here's the full component:</p>
  
  <pre><code>import React from 'react';
  import firebase from '../../firebase';
  import {Col, Button, Modal} from 'react-bootstrap';
  import Dropzone from 'react-dropzone';
  import CancelAnswerButton from '../answer/CancelAnswerButton';
  import FinishAnswerButton from '../answer/FinishAnswerButton';
  import AnswerComponent from '../answer/AnswerComponent';
  import MetaTags from 'react-meta-tags';
  import {Redirect} from 'react-router';
  import './AssignmentComponent.css';
  import 'font-awesome/css/font-awesome.min.css';
  import Time from '../globalMethods/Time';
  
  export default class AssignmentComponent extends React.Component {
      async componentWillMount() {
          firebase.database().ref('Users').child(firebase.auth().currentUser.uid).on('value', snap =&gt; {
              if (snap.val().assignedWork) {
                  this.setState({hasAssignedTask: true});
              } else {
                  this.setState({hasAssignedTask: false});
              }
          });
  
          const assignmentsRef = firebase.database().ref('Works').orderByChild('firebaseKey').equalTo(this.props.assignmentId);
          await assignmentsRef.on('value', snapshot =&gt; {
              var assignments = snapshot.val();
              var newState = [];
              for (let assignment in assignments) {
                  let currentAssignment = assignments[assignment];
                  newState.push({
                      id: assignment,
                      category: currentAssignment.category,
                      level: currentAssignment.level,
                      pointAmount: currentAssignment.pointAmount,
                      pointBoost: currentAssignment.pointBoost,
                      points: currentAssignment.pointBoost + currentAssignment.pointAmount,
                      photoURL: currentAssignment.photoURL,
                      workText: currentAssignment.workText,
                      answers: currentAssignment.answers,
                  });
              }
              var answers = [];
              for (let answer in newState[0].answers) {
                  let currAns = newState[0].answers[answer];
                  answers.push({
                      id: answer,
                      textAnswer: currAns.textAnswer,
                      downloadURL: currAns.downloadURL,
                  })
              }
              this.setState({
                  assignments: newState,
                  answers: answers,
              });
          });
      }
  
      constructor(props) {
          super(props);
          this.state = {
              assignments: [],
              answers: [],
              uploadedFile: '',
              showTimeoutModal: false,
          };
          this.onImageDrop = this.onImageDrop.bind(this);
          this.startCountDown = this.startCountDown.bind(this);
          this.handleTimeoutButtonClick = this.handleTimeoutButtonClick.bind(this);
      }
  
      componentDidMount() {
          clearTimeout(this.state.timer);
          firebase.database().ref('Works').child(this.props.assignmentId).once('value', function () {
              // var startTime = r.val().acceptedDate.time;
              var startTime = Time.generate().time; //todo change to db specific time
              var waitingTime = Time.makeMinutes(5);
              var endTime = Time.generate().time + waitingTime;
              this.setState({timer: this.startCountDown(startTime, endTime)});
          }.bind(this)).catch(e =&gt; console.log(e));
      }
  
      componentWillUnmount() {
          clearTimeout(this.state.timer);
      }
  
      startCountDown(startTime, endTime) {
          var timeout = setTimeout(function () {
              var now = startTime;
              console.log(endTime - now);
              if (now &gt;= endTime) {
                  clearTimeout(timeout);
                  console.log(true);
                  this.setState({showTimeoutModal: true});
              } else {
                  now = Time.generate().time;
                  this.setState({timer: this.startCountDown(now, endTime)});
              }
          }.bind(this), 1000);
          return timeout;
      }
  
      handleTimeoutButtonClick() {
          var startTime = Time.generate().time;
          var waitingTime = Time.makeMinutes(0.15);
          var endTime = Time.generate().time + waitingTime;
  
          this.setState({showTimeoutModal: false, timer: this.startCountDown(startTime, endTime)});
      }
  
      async onImageDrop(files) {
          await this.setState({
              uploadedFile: files[0],
          });
          await AnswerComponent.handleImageSubmit(files[0], this.props);
      }
  
      render() {
          return (
              this.state.assignments.map(assignment =&gt; {
                  return (
                      this.state.hasAssignedTask ?
                          &lt;section key={assignment.id} className='display-assignment'&gt;
                              &lt;MetaTags&gt;
                                  &lt;title&gt;Zadanie&lt;/title&gt;
                              &lt;/MetaTags&gt;
                              &lt;div style={{height: '150px', background: '#fff', borderBottom: '2px solid #e0e0e0'}}&gt;
                                  &lt;div className='container'&gt;
                                      &lt;h4 style={{
                                          paddingTop: '75px',
                                          fontSize: '24px',
                                          textAlign: 'left'
                                      }}&gt;Aktualnie rozwiązywane zadanie&lt;/h4&gt;
                                  &lt;/div&gt;
                              &lt;/div&gt;
                              &lt;div className='wrapper show-grid task_info container-fluid task_solve_content'&gt;
                                  &lt;Col xs={12} md={6}&gt;
                                      &lt;img className='task_img' alt='' src={assignment.photoURL}/&gt;
                                      &lt;p&gt;{assignment.workText}&lt;/p&gt;
                                  &lt;/Col&gt;
                                  &lt;Col xs={12} md={6}&gt;
                                      &lt;div className='row task_info_content'&gt;
                                          &lt;div className='col-sm-4 col-md-4 col-lg-4'&gt;
                                              &lt;h3 className='text-center gradient_text'&gt;
                                                  {assignment.category}
                                              &lt;/h3&gt;
                                              &lt;h4 className='text-center'&gt;przedmiot&lt;/h4&gt;
                                          &lt;/div&gt;
                                          &lt;div className='col-sm-4 col-md-4 col-lg-4'&gt;
                                              &lt;h3 className='text-center gradient_text'&gt;
                                                  {assignment.level}&lt;/h3&gt;
                                              &lt;h4 className='text-center'&gt;poziom&lt;/h4&gt;
                                          &lt;/div&gt;
                                          &lt;div className='col-sm-4 col-md-4 col-lg-4'&gt;
                                              &lt;h3 className='text-center gradient_text'&gt;
                                                  {assignment.points}&lt;/h3&gt;
                                              &lt;h4&gt;punkty&lt;/h4&gt;
                                          &lt;/div&gt;
                                      &lt;/div&gt;
                                      &lt;form encType="multipart/form-data"&gt;
                                          &lt;textarea placeholder='Wpisz rozwiązanie...' name="textAnswer" id="textAnswer"
                                                    style={{
                                                        width: '100%',
                                                        height: '80vh',
                                                        background: 'white',
                                                        color: 'black',
                                                    }}/&gt;
                                          &lt;div style={{width: '100%', height: '60px', position: 'relative'}}&gt;
                                              &lt;Button className="send_text_answer_button"
                                                      onClick={() =&gt; AnswerComponent.handleTextSubmit(this.props)}
                                                      style={{display: 'block'}}&gt;
                                                  &lt;span&gt;Wyslij odpowiedź tekstową&lt;/span&gt;
                                              &lt;/Button&gt;
  
                                          &lt;/div&gt;
                                          &lt;Dropzone
                                              className='dropzone'
                                              multiple={false}
                                              accept='image/*'
                                              style={{
                                                  backgroundColor: '#fff',
                                                  border: '1px solid #fff',
                                                  borderBottom: '2px solid #e0e0e0',
                                                  borderRadius: '4px',
                                                  width: '100%',
                                                  height: '300px',
                                                  marginBottom: '20px'
                                              }}
                                              onDrop={this.onImageDrop.bind(this)}&gt;
  
                                              &lt;i className='fa fa-image' style={{
                                                  fontSize: '64px',
                                                  marginRight: '5px',
                                                  color: '#e0e0e0',
                                                  margin: 'auto',
                                                  marginTop: '120px'
                                              }}/&gt;
                                          &lt;/Dropzone&gt;
                                          &lt;h3 style={{display: 'none', color: 'red'}}
                                              id='error'&gt;Upewnij sie ze dodana jest przynajmniej jedna odpowiedz!&lt;/h3&gt;
                                          &lt;div id='answers'&gt;
                                              &lt;h3 style={{
                                                  fontSize: '18px',
                                                  fontWeight: 'lighter',
                                                  marginTop: '10px',
                                                  marginBottom: '10px'
                                              }}&gt;Odpowiedzi przeslane do tej pory&lt;/h3&gt;
                                              {
                                                  this.state.answers.map(answer =&gt; {
                                                      return (
                                                          &lt;Col xs={12} md={12} key={answer.id}&gt;
                                                              {
                                                                  answer.textAnswer !== undefined &amp;&amp;
                                                                  answer.textAnswer.length &gt; 0 ?
                                                                      &lt;div className='task_info_text_answer'&gt;
                                                                          &lt;p&gt;{answer.textAnswer}&lt;/p&gt;
                                                                      &lt;/div&gt;
                                                                      :
                                                                      &lt;img className="your_answer_img"
                                                                           src={answer.downloadURL}
                                                                           alt=""/&gt;
                                                              }
                                                              &lt;br/&gt;
                                                              &lt;Button className="delete_answer_button"
                                                                      onClick={() =&gt; AnswerComponent.removeAnswer(this.props, answer.id)}&gt;
                                                                  &lt;span&gt;Usuń odpowiedź&lt;/span&gt;
                                                              &lt;/Button&gt;
                                                          &lt;/Col&gt;
                                                      )
                                                  })
                                              }
                                          &lt;/div&gt;
  
                                          &lt;div className="row" style={{marginTop: '50px', marginBottom: '100px'}}&gt;
                                              &lt;div className="col-sm-6 col-md-6 col-lg-6 cancel_answer_button_content"
                                                   style={{height: '200px'}}&gt;
                                                  &lt;CancelAnswerButton className="send_text_cancel_answer_button"
                                                                      points={assignment.pointAmount + assignment.pointBoost}
                                                                      assignmentId={assignment.id}/&gt;
                                                  &lt;div className="cancel_answer_button_info"&gt;
                                                      &lt;p&gt;Za anulowanie zadania grozi odjęcie punktów z rangi!&lt;/p&gt;
                                                  &lt;/div&gt;
                                              &lt;/div&gt;
                                              &lt;div className="col-sm-6 col-md-6 col-lg-6 finish_answer_button_content"
                                                   style={{height: '200px'}}&gt;
                                                  &lt;FinishAnswerButton className="send_text_finish_button"
                                                                      points={assignment.pointAmount + assignment.pointBoost}
                                                                      assignmentId={assignment.id}/&gt;
                                                  &lt;div className="finish_answer_button_info"&gt;
                                                      &lt;p&gt;Upewnij się, że uczeń dostał wszystko, czego potrzebuje!&lt;/p&gt;
                                                  &lt;/div&gt;
                                              &lt;/div&gt;
                                          &lt;/div&gt;
                                      &lt;/form&gt;
                                  &lt;/Col&gt;
                              &lt;/div&gt;
                              &lt;Modal show={this.state.showTimeoutModal}&gt;
                                  &lt;Modal.Header&gt;
                                      Hej! Rozwiazujesz dalej to zadanie?
                                  &lt;/Modal.Header&gt;
                                  &lt;Modal.Body&gt;
                                      &lt;h3&gt;Pozostaly czas: {this.state.timeLeft / 1000}&lt;/h3&gt;
                                      &lt;Button className='btn btn-primary' onClick={this.handleTimeoutButtonClick}&gt;Tak! Daj
                                          mi jeszcze 5 minut! &lt;/Button&gt;
                                  &lt;/Modal.Body&gt;
                              &lt;/Modal&gt;
                          &lt;/section&gt;
                          :
                          &lt;Redirect to='/assignments'/&gt;
                  )
              })
          )
      }
  }
  </code></pre>
  
  <p>So how can I make the timer run just once? What am I missing?</p>
  
  <p>Logs in the console after the first click:</p>
  
  <pre><code>300000 AssignmentComponent.js:89
  298999 AssignmentComponent.js:89
  297997 AssignmentComponent.js:89
  296996 AssignmentComponent.js:89
  295994 AssignmentComponent.js:89
  294992 AssignmentComponent.js:89
  293990 AssignmentComponent.js:89
  292988 AssignmentComponent.js:89
  291986 AssignmentComponent.js:89
  290984 AssignmentComponent.js:89
  289983 AssignmentComponent.js:89
  </code></pre>
  
  <p>Logs after the second click:</p>
  
  <pre><code>300000 AssignmentComponent.js:89
  298993 AssignmentComponent.js:89
  298999 AssignmentComponent.js:89
  297992 AssignmentComponent.js:89
  297997 AssignmentComponent.js:89
  296990 AssignmentComponent.js:89
  296996 AssignmentComponent.js:89
  295981 AssignmentComponent.js:89
  295993 AssignmentComponent.js:89
  294980 AssignmentComponent.js:89
  294991 AssignmentComponent.js:89
  </code></pre>
  
  <p>Also I just realized, it doesn't only run twice. It starts a new timer, for each click. So if you recreate the component 5 times, there will be 5 timers running next to each other.</p>