title: ListView of objects updated asynchronously
body: <p>I'm trying to create a ListView that displays a list of objects received by an event handler function. Objects are received asynchronously and one at a time (similar to <a href="https://facebook.github.io/react-native/docs/listviewdatasource.html" rel="nofollow noreferrer">ListViewDataSource documentation</a>'s scenario).</p>
  
  <p>Each object has an ID and a value field (among others irrelevant here).
  The ListView would display both fields for each object.</p>
  
  <p>The handler can receive multiple objects with the same ID, but different values. In this case, the ListView should update the entry with the new value.</p>
  
  <p>Inserting new items to the ListView work fine, But I updating existing items does not. How to do it?</p>
  
  <p>Follow up question: What if I want to sort the elements in the ListView by the value field? What's the best way to do it?</p>
  
  <p>Pseudo(ish) code for the Object:</p>
  
  <pre><code>class DataObj {
    objid: string;
    value: string;
  
    static create(rawData: string) : ?DataObj {
      if (Invalid data) return null;
  
      let dataObj = new DataObj();
      dataObj.objid = ...;
      dataObj.value = ...;
      return dataObj;
    }
  
    static equal(lhs: DataObj, rhs: DataObj) {
      return (lhs.objid === rhs.objid &amp;&amp; lhs.value === rhs.value);
    }
  }
  </code></pre>
  
  <p>Code for the component:</p>
  
  <pre><code>type State = {
    items: ListView.DataSource,
  };
  
  class MyComponent extends React.Component {
    state: State;
  
    _items = {};
  
    constructor(props: Props, context: {}) {
      super(props, context);
  
      const ds = new ListView.DataSource({
        rowHasChanged: (r1, r2) =&gt; !DataObj.equal(r1, r2)
      });
      this.state = {
        items: ds.cloneWithRows(this._items),
      };
    }
  
    _onNewItem = async (rawData: string) =&gt; {
      const newItem = DataObj.create(rawData);
      if (newItem) {
        // Valid item
        let oldItem = this._items[newItem.objid];
        if (!old || !DataObj.equal(oldItem, newItem)) {
          // New item or updated item
          // Clone _items, since it must be immutable, and add new item to it.
          let newItems = Object.assign({}, this._items);
          newItems[newItem.objid] = newItem;
          // update _items reference to its modified clone.
          this._items = newItems;
          // Update the state
          this.setState(({items}) =&gt; ({
            items: items.cloneWithRows(newItems),
          }));
        }
      }
    };
  
    render(): React.Element&lt;*&gt; {
      return (
        &lt;ListView
          dataSource={this.state.items}
          enableEmptySections={true}
          renderRow={this._renderDataObj} /&gt;
      );
    }
  
    _renderDataObj = (
      obj: DataObj,
      sectionID: number,
      rowID: number
    ) : React.Element&lt;*&gt; =&gt; {
      return (
        &lt;DataObjRenderer
          key={obj.objid}
          objid={obj.objid}
          value={obj.value}
        /&gt;
      );
    }
  }
  </code></pre>