title: React Js component rendering only once after state change
body: <p>I'm quite new to ReactJS and my problems is quite unusual, may be occurring simply because I don't implement things the way they are meant to be.</p>
  
  <p>So basically speaking, this was working fine before, but I needed to add some new features, and... well, something's off.</p>
  
  <p>To start with - <code>ConvFrame</code> is top component, appearing at the top on the page and it consists of <code>ConvForm</code> component (to add new queries) and <code>ConvList</code> where unassigned and new calls go. The <code>ConvList</code> here has ID and Key of 1.</p>
  
  <p>There is also list of workers below, they are using <code>ConvForm</code> only, the fields themselves are dropzones, which allow to assign new call tasks quickly. The <code>ConvList</code> here have Id and Key equal to id of worker.</p>
  
  <p>As the <code>ConvList</code> is rendered it queries server for jobs within the list. And this works just fine for all of them. However, there seems to be some weird problem when new item is added via <code>ConvForm</code>. It calls <code>handleCommentSubmit()</code> function, calls <code>this.loadCommentsFromServer();</code> (stupid, I know!) and then sets new state for records <code>this.setState({records: data});</code></p>
  
  <p>When first record is added the <code>/api/zlecenia</code> is called twice. Once from the <code>loadCommentsFromServer()</code> inside <code>ConvFrame</code> and second time from within <code>ConvList</code>. Adding second record via form calls it once, the component seem to not react to the state change. Something is badly implemented , I guess.</p>
  
  <p>Here's the source code:
  Conversations.js</p>
  
  <pre><code>//For dragging
  var placeholder = document.createElement("div");
  placeholder.className = "placeholder";
  var dragged;
  var over;
  
  /**
   * Conversation
   * Should be used for listing conversation blocks, adds class based on age of task.
   * Detects drag events, renders block, calls dragEnd function to append block to new
   * location and uses props.OnDrop function to pass id of element and target id of worker
   */
  window.Conversation = React.createClass({
      dynamicClass: function () {
          return "convo " + this.props.delay;
      },
      dragStart: function (e) {
          dragged = e.currentTarget;
          over = null;
          e.dataTransfer.effectAllowed = 'move';
          e.dataTransfer.setData("text/html", e.currentTarget);
      },
      dragEnd: function (e) {
          $(dragged).show();
          $(placeholder).remove();
              console.log(over, over.className);
          if (over &amp;&amp; over.className === "candrop") {
              var id = Number(dragged.dataset.id);
  
              this.props.onDrop({id: id, target: over.id});
              over.appendChild(dragged);
          }else{
              console.log('returning base:' + over);
             $(dragged).parent().append(dragged);
          }
      },
    render: function() {
      return (
        &lt;div draggable="true" data-id={this.props.id} onDragEnd={this.dragEnd} onDragStart={this.dragStart} className={this.dynamicClass()}  &gt;
          {this.props.children}
        &lt;/div&gt;
      );
    }
  });
  
  /**
   * ConvList
   * Displays conversation dropdown list. I should aim to make it single component, do not repeat for workers.
   * Detects dragOver for .candrop and place some funny placeholder. Detect position change from Conversation view
   * call master class from parent component and pass data. Detect delete event.
   */
  window.ConvList = React.createClass({
      getInitialState: function () {
          return {data: []};
      },
      loadConvsFromServer: function () {
          $.ajax({
              url: baseUrl + '/api/zlecenia',
              type: 'GET',
              data: {id: this.props.id},
              success: function (data) {
                  this.setState({data: data});
              }.bind(this),
              error: function (xhr, status, err) {
                  console.error(this.props.url, status, err.toString());
              }.bind(this)
          });
      },
      componentDidMount: function () {
          this.loadConvsFromServer();
      },
      dragOver: function (e) {
          e.preventDefault();
          $(dragged).fadeOut();
          if (e.target.className === "candrop") {
              if (e.target.className == "placeholder")
                  return;
              over = e.target;
              e.target.appendChild(placeholder, e.target);
          }
      },
      updatePosition: function (data) {
          console.log('update convo %d for member %e', data.id, data.target);
  
          $.ajax({
              url: baseUrl + '/api/zlecenia',
              type: 'PUT',
              data: {id: data.id, assign: data.target},
              success: function (data) {
              }.bind(this),
              error: function (xhr, status, err) {
                  console.error(this.props.url, status, err.toString());
              }.bind(this)
          });
      },
      deleteTask: function (e) {
          var taskIndex = parseInt(e.target.value, 10);
          console.log('remove task: %d', taskIndex);
  
          $.ajax({
              url: baseUrl + '/api/zlecenia/' + taskIndex,
              type: 'DELETE',
              success: function (data) {
                  this.loadConvsFromServer();
              }.bind(this),
              error: function (xhr, status, err) {
                  console.error(this.props.url, status, err.toString());
              }.bind(this)
          });
  
      },
      render: function () {
        return (
         &lt;div className="convlist" onDragOver={this.dragOver}&gt;
              &lt;div className="candrop" id={this.props.id} &gt;{this.props.id}
                  {this.state.data.map((c) =&gt; 
                      &lt;Conversation  onDrop={this.updatePosition} delay={c.delayTime} id={c.id} key={c.id}&gt;
                          &lt;p className="convTop"&gt;{c.formattedTime} | Tel. {c.phone} | {c.name} | Nr.Rej {c.number}&lt;/p&gt;
                          &lt;p&gt;{c.text}&lt;/p&gt;
                          &lt;button className="deleteConv"  onClick={this.deleteTask} value={c.id}&gt;x&lt;/button&gt;
                       &lt;/Conversation&gt;
                  )}
              &lt;/div&gt;
          &lt;/div&gt;
  
        );
      }
  });
  
  /**
   * ConvForm
   * Displays conversation create form. Prepares fields, validates them.
   * Call master function to add new record on send.
   */
  var ConvForm = React.createClass({
      getInitialState: function () {
          return {phone: '', name: '', number: '', text: ''};
      },
      handlePhoneChange: function (e) {
          this.setState({phone: e.target.value});
      },
      handleNameChange: function (e) {
          this.setState({name: e.target.value});
      },
      handleNumberChange: function (e) {
          this.setState({number: e.target.value});
      },
      handleTextChange: function (e) {
          this.setState({text: e.target.value});
      },
      submitForm: function (e) {
          e.preventDefault();
          var phone = this.state.phone.trim();
          var name = this.state.name.trim();
          var number = this.state.number.trim();
          var text = this.state.text.trim();
  
          if (!text || !phone || !name || !number) {
              return;
          }
          this.props.onConvSubmit({phone: phone, name: name, number: number, text: text});
          this.setState({phone: '', text: '', number: '', name: ''});
      },
      render: function () {
          return (
          &lt;form className="convForm" onSubmit={this.submitForm}&gt;
              &lt;div className="row"&gt;
                  &lt;div className="col-xs-12 col-md-4"&gt;
                      &lt;div className="form-group"&gt;
                          &lt;input
                          className="form-control"
                          type="text"
                          placeholder="Telefon"
                          value={this.state.phone}
                          onChange={this.handlePhoneChange}
                          /&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div className="col-xs-12 col-md-4"&gt;
                      &lt;div className="form-group"&gt;
                          &lt;input
                          className="form-control"
                          type="text"
                          placeholder="Imię i nazwisko"
                          value={this.state.name}
                          onChange={this.handleNameChange}
                        /&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div className="col-xs-12 col-md-4"&gt;
                      &lt;div className="form-group"&gt;
                          &lt;input
                          className="form-control"
                          type="text"
                          placeholder="Nr. rejestracyjny"
                          value={this.state.number}
                          onChange={this.handleNumberChange}
                        /&gt;
                      &lt;/div&gt;
                   &lt;/div&gt;
              &lt;/div&gt;
              &lt;div className="form-group"&gt;
                  &lt;textarea
                  className="form-control"
                  type="text"
                  placeholder="Treść"
                  value={this.state.text}
                  onChange={this.handleTextChange}
                  /&gt;
              &lt;/div&gt;
              &lt;input className="btn btn-success" type="submit" value="Zapisz" /&gt;
          &lt;/form&gt;
                  );
      }
  });
  
  /**
   * ConvFrame
   * Conversation main frame and root functions for both form and conversations listing.
   */
  window.ConvFrame = React.createClass({
      getInitialState: function () {
          return {records: []};
      },
      loadCommentsFromServer: function () {
          $.ajax({
              url: baseUrl + '/api/zlecenia',
              type: 'GET',
              data: {id : 1},
              success: function (data) {
                  this.setState({records: data});
              }.bind(this),
              error: function (xhr, status, err) {
                  console.error(this.props.url, status, err.toString());
              }.bind(this)
          });
      },
      handleCommentSubmit: function (convo) {
          $.ajax({
              url: baseUrl + '/api/zlecenia',
              type: 'POST',
              data: convo,
              success: function (data) {
                  this.loadCommentsFromServer();
              }.bind(this),
              error: function (xhr, status, err) {
                  console.error(this.props.url, status, err.toString());
              }.bind(this)
          });
      },
    render: function() {
          return (
                  &lt;div className="add-new"&gt;
                          &lt;div className="row"&gt;
                              &lt;div className="col-xs-12 col-md-12 frame"&gt;
                                  &lt;div className="col-xs-12 col-md-7"&gt;
                                      &lt;h3&gt;Dodaj nową rozmowę&lt;/h3&gt;
                                      &lt;ConvForm onConvSubmit={this.handleCommentSubmit} /&gt;
                                  &lt;/div&gt;
                                  &lt;div className="col-xs-12 col-md-5"&gt;
                                      &lt;ConvList key='1' id='1'  data={this.state.records} /&gt;
                                  &lt;/div&gt;  
                              &lt;/div&gt;
                          &lt;/div&gt;
                  &lt;/div&gt;
                  );
      }
  });
  </code></pre>
  
  <p>workers.js</p>
  
  <pre><code>/**
   * WorkerList
   * 
   */
  var Worker = React.createClass({
      render: function () {
        return (
           &lt;div&gt;
                {this.props.children}
           &lt;/div&gt;
        );
      }
  });
  
  
  /**
   * WorkerList
   * 
   */
  var WorkerList = React.createClass({
      render: function () {
        return (
         &lt;div className="worker-list"&gt;
                  {this.props.data.map((worker) =&gt; 
                      &lt;Worker id={worker.id} key={worker.id}&gt;
                          &lt;div className="row"&gt;
                              &lt;div className="col-xs-12 col-md-12 frame"&gt;
                                  &lt;div className="col-xs-12 col-md-5"&gt;
                                       &lt;h4&gt;{worker.username}&lt;/h4&gt;
                                  &lt;/div&gt;
                                  &lt;div className="col-xs-12 col-md-7"&gt;
                                  &lt;ConvList key={worker.id} id={worker.id} /&gt;
                                  &lt;/div&gt;  
                             &lt;/div&gt;
                          &lt;/div&gt;
                      &lt;/Worker&gt;
                  )}
  
          &lt;/div&gt;
  
        );
      }
  });
  
  /**
   * WorkerForm
   * 
   */
  var WorkerForm = React.createClass({
    render: function() {
      return (
        &lt;div&gt;
        &lt;/div&gt;
      );
    }
  });
  
  
  /**
   * WorkerFame
   * 
   */
  window.WorkerFrame = React.createClass({
      getInitialState: function () {
          return {data: []};
      },
      loadWorkersFromServer: function () {
          $.ajax({
              url: baseUrl + '/api/pracownicy',
              type: 'GET',
              success: function (data) {
                  this.setState({data: data});
              }.bind(this),
              error: function (xhr, status, err) {
                  console.error(this.props.url, status, err.toString());
              }.bind(this)
          });
      },
      componentDidMount: function () {
          this.loadWorkersFromServer();
      },
      handleWorkerSubmit: function (worker) {
          $.ajax({
              url: baseUrl + '/api/pracownicy',
              type: 'POST',
              data: worker,
              success: function (data) {
                  this.loadWorkersFromServer();
              }.bind(this),
              error: function (xhr, status, err) {
                  console.error(this.props.url, status, err.toString());
              }.bind(this)
          });
      },
    render: function() {
          return (
                  &lt;div className="add-new"&gt;
                          &lt;div className="row"&gt;
                              &lt;div className="col-xs-12 col-md-12"&gt;
                                  &lt;WorkerList data={this.state.data} /&gt;
                              &lt;/div&gt;  
                             &lt;div className="col-xs-12 col-md-12"&gt;
                                  &lt;WorkerForm onWorkerSubmit={this.handleWorkerSubmit} /&gt;
                              &lt;/div&gt;
                          &lt;/div&gt;
                  &lt;/div&gt;
                  );
      }
  });
  </code></pre>
  
  <p>final.js</p>
  
  <pre><code>var DashFrame = React.createClass({
    render: function() {
      return (
        &lt;div&gt;
        &lt;ConvFrame/&gt;
        &lt;WorkerFrame/&gt;
        &lt;/div&gt;
      );
    }
  });
  
  
  ReactDOM.render(
    &lt;DashFrame/&gt;,
    document.getElementById('dashboard')
  );
  </code></pre>
  
  <p>Any hints would be appreciated. My brain is boiling. </p>