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