对象的ListView异步更新

时间:2017-04-24 19:45:35

标签: reactjs

我正在尝试创建一个ListView,它显示事件处理函数接收的对象列表。对象是异步接收的,一次接收一个对象(类似于ListViewDataSource documentation的场景)。

每个对象都有一个ID和一个值字段(此处不相关)。 ListView将显示每个对象的两个字段。

处理程序可以接收具有相同ID但具有不同值的多个对象。在这种情况下,ListView应使用新值更新条目。

将新项目插入ListView工作正常,但我更新现有项目没有。怎么做?

跟进问题:如果我想通过值字段对ListView中的元素进行排序,该怎么办?最好的方法是什么?

Object的伪(ish)代码:

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 && lhs.value === rhs.value);
  }
}

组件代码:

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) => !DataObj.equal(r1, r2)
    });
    this.state = {
      items: ds.cloneWithRows(this._items),
    };
  }

  _onNewItem = async (rawData: string) => {
    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}) => ({
          items: items.cloneWithRows(newItems),
        }));
      }
    }
  };

  render(): React.Element<*> {
    return (
      <ListView
        dataSource={this.state.items}
        enableEmptySections={true}
        renderRow={this._renderDataObj} />
    );
  }

  _renderDataObj = (
    obj: DataObj,
    sectionID: number,
    rowID: number
  ) : React.Element<*> => {
    return (
      <DataObjRenderer
        key={obj.objid}
        objid={obj.objid}
        value={obj.value}
      />
    );
  }
}

2 个答案:

答案 0 :(得分:0)

根据W3C documentation,您可以按如下方式对数组进行排序:

const points = [
    {
        name: 'Alpha',
        score: 40
    },
    {
        name: 'Bravo',
        score: 100
    },
    {
        name: 'Charlie',
        score: 1
    }
];

points.sort((a, b) => {
    return a.score - b.score;
});

使用Lodash,它会更清晰:

_.orderBy(points, ['user', 'age'], 

答案 1 :(得分:0)

使用ListView可以部分解决问题。 项的关键属性必须包括可能导致重新渲染的所有属性。

但是,最好的解决方案是使用FlatList,它取代了即将被弃用的ListView。 使用与FlatList相同的关键技巧解决了我遇到的所有问题。