How to optimize item update in ListView

I am making a simple reaction of a native application that has multiple lists, and gives the user the opportunity to update an item in any of these lists or add new items to the list.

However, as it was previously pointed out at https://stackoverflow.com/a/1377070/... , you cannot add or move an item in a ListView, since it must be immutable data composition. that is, in this code you cannot insert a new element into the data source.

var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); var data = ds.cloneWithRows(responseData) var obj = {}; obj['someproperty'] = 'foo'; data.push(obj); //cannot push a new item into data 

So, I made instead a copy ( this.state.items; in the code below) of the data that I retrieve from the server (and which I call cloneWithRows on), join this copy (or update it if it's editing), and then call cloneWithRows in a mutated copy each time you change (either by editing or creating a new element), or update ui and then update the server (this last part is outside the scope of the response native application). So, in general, I have a copy of the data that I can mutate for use as a data source for ds.cloneWithRows when I make changes

However, it doesn't seem to make sense to store a cache of the data structure with which I can mutate, for the sole purpose of using it as a source for an immutable data structure ( listForUI: ds.cloneWithRows(t) in the code below) if I want to optimistically update the interface (i.e. show the change before saving it to the server).

An alternative (also not making much sense to me) seems to be updating the server and waiting for a response (without saving any kind of cache) anytime I update or add a new item to my list, but will it be slow?

Question: With the exception of saving the modified copy of the data as a cache, is there a way to optimistically update the ui in the response native?

 addNewItemToList: function(){ var t = this.state.items; //my cache of list items var newListItem = {}; newListItem['id'] = 123; t.push(newListItem); //adding-mutating the cache //creating a new immutable ds var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); this.setState({ listForUI: ds.cloneWithRows(t) }, function(){ //update server with change fetch('http://localhost:8080/accounts/1/lists/3/todos', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, //code ommitted } } 
+7
reactjs react-native
source share
2 answers

No, I'm sure there is no other way to update the ListView data source, because, as you explain, it is immutable. Consistency implies that you will always need to make a copy of something before adding to it.

You mentioned:

However, it doesn't seem to make sense to store the cache of the data structure with which I can mutate, for the sole purpose of using it as a source for an immutable data structure ...

I'm not sure why you feel that keeping this cache does not make sense. I also see no reason for this with performance issues, as the cache only exists for a short while while addNewItemToList is addNewItemToList .

+1
source share

You will need to keep the previous items if you want to cancel the optimistic update. To do this, you will need to "cache" or store a link to previous data.

You can optimize the call to this.setState in your addNewItemToList handler and update your state (causing re-rendering), and then in fetch you can undo the change if necessary (i.e. if the call fails):

 addNewItemToList: function(id) { // Store current list of items and calculate new list var prevItems = this.state.listForUI.slice(); var newItems = this.state.items.concat([id]); // Optimistically set new items list; will cause a re-render this.setState({ listForUI: this.state.listForUI.cloneWithRows(newItems) }); // Update server with change fetch('http://localhost:8080/accounts/1/lists/3/todos', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, //code ommitted }) // Catch an error and revert change .catch(function (ex) { this.setState({ listForUI: this.state.listForUI.cloneWithRows(prevItems) }); }); } 
+1
source share

All Articles