2017-04-24 2 views
2

Ich versuche, eine ListView zu erstellen, die eine Liste der Objekte anzeigt, die von einer Ereignishandlerfunktion empfangen werden. Objekte werden asynchron und nacheinander empfangen (ähnlich dem Szenario ListViewDataSource documentation).ListView der Objekte, die asynchron aktualisiert werden

Jedes Objekt hat eine ID und ein Wertfeld (ua irrelevant). Die ListView würde beide Felder für jedes Objekt anzeigen.

Der Handler kann mehrere Objekte mit derselben ID, aber unterschiedlichen Werten empfangen. In diesem Fall sollte der ListView den Eintrag mit dem neuen Wert aktualisieren.

Das Einfügen neuer Elemente in die ListView funktioniert gut, aber ich aktualisiere vorhandene Elemente nicht. Wie es geht?

Folgefrage: Was, wenn ich die Elemente in der ListView nach dem Wertfeld sortieren möchte? Was ist der beste Weg, es zu tun?

Pseudo (ish) Code für das Objekt:

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); 
    } 
} 

-Code für die Komponente:

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

Antwort

0

Es ist teilweise möglich, das Problem mit ListView zu lösen. Die Schlüsseleigenschaft von Elementen muss alle Eigenschaften enthalten, die zu einem erneuten Rendern führen würden.

Die beste Lösung ist jedoch die Verwendung von FlatList, die das bald veraltete ListView ersetzt. Mit dem gleichen Schlüssel Trick mit FlatList löste ich alle Probleme, die ich hatte.

0

Nach W3C documentation, können Sie ein Array wie folgt sortieren:

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

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

Mit Lodash wäre es sauberer:

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

In der Tat sortiert es das Array. Die Nachfolgefrage wäre, eine Karte zu verwenden, um die Objekte zu speichern und sie bei Bedarf zu aktualisieren. Dann wäre es notwendig, ein Array mit seinen Elementen zu erhalten: Array.from (this._items.values ​​()). Dann sortiere es. Es verursacht jedoch ein anderes Problem: React ignoriert, wenn ich die Eigenschaften eines DataObject ändere. Ich habe versucht, alle "beobachtbaren" Eigenschaften dem Schlüssel des ListView-Elements hinzuzufügen. Es funktioniert aber auch nicht gut. – Marcus

Verwandte Themen