2017-04-24 39 views
2

我试图创建一个ListView,显示事件处理函数接收到的对象列表。对象是异步接收的,并且每次接收一个对象(类似于ListViewDataSource documentation的场景)。异步更新对象的ListView

每个对象都有一个ID和一个值字段(其中与此无关)。 ListView将显示每个对象的两个字段。

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

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

后续问题:如果我想通过值字段对ListView中的元素进行排序,该怎么办?什么是最好的方式来做到这一点?

为对象

伪(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} 
     /> 
    ); 
    } 
} 

回答

0

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

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

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'], 
+0

的确,它对数组进行排序。后续问题是关于使用地图来存储对象并根据需要进行更新。然后有必要得到一个数组:Array.from(this._items.values())。然后整理它。但是它会导致另一个问题:React会忽略更改DataObject的属性。我试图将所有“可观察”属性添加到ListView元素的键。但它也不能很好地工作。 – Marcus