Как оптимистично обновить элемент в ListView

7

Я делаю простую реакцию родного приложения, имеющего несколько списков, и дает пользователю возможность обновить элемент в любом из этих списков или добавить новые элементы в список.

Однако, как ранее указывалось на https://stackoverflow.com/questions/29351259/how-to-add-delete-item-into-listview, нельзя добавлять или перемещать элемент в ListView, поскольку он должен быть неизменяемыми данными состав. то есть в этом коде нельзя вставить новый элемент в источник данных.

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

Итак, я сделал вместо этого копию (this.state.items; в коде ниже) данных, которые я извлекаю с сервера (и который я вызываю cloneWithRows on), присоединяюсь к этой копии (или обновляю ее если это редактирование), а затем вызовите cloneWithRows в мутированной копии при каждом изменении (либо путем редактирования, либо создания нового элемента), либо обновите ui, а затем обновите сервер (эта последняя часть вне области ответного родного приложения). Итак, в общем, у меня есть копия данных, которые я могу мутировать для использования в качестве источника данных для ds.cloneWithRows, когда я делаю изменения

Однако, похоже, не имеет смысла хранить кэш структуры данных, с которой я могу мутировать, с единственной целью использовать его в качестве источника для неизменяемой структуры данных (listForUI: ds.cloneWithRows(t) в приведенном ниже коде) если я хочу оптимистично обновить интерфейс (т.е. показать изменение до его сохранения на сервере).

Альтернатива (также не имеющая для меня большого смысла), похоже, будет обновлять сервер и ждать ответа (без сохранения кеша любого вида) в любое время, когда я обновляю или добавляю новый элемент в свой список, но это будет медленным?

Вопрос: За исключением сохранения измененной копии данных в виде кеша, есть ли способ оптимистично обновить ui в ответном 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
  }

 }
Теги:
react-native

2 ответа

1

Вам нужно будет сохранить предыдущие элементы, если вы хотите отменить оптимистичное обновление. Для этого вам нужно будет "кэшировать" или хранить ссылку на предыдущие данные.

Вы можете оптимизировать вызов this.setState в вашем обработчике addNewItemToList и обновить свое состояние (вызывая повторную визуализацию), а затем в fetch вы можете отменить изменение, если необходимо (т.е. если сбой вызова):

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

Нет, я уверен, что нет никакого другого способа обновить источник данных ListView, поскольку, как вы объясните, он неизменен. Неизменность подразумевает, что вам всегда нужно будет сделать копию чего-либо, прежде чем добавлять к ней.

Вы упомянули:

Однако, похоже, не имеет смысла хранить кэш структуры данных, с которой я могу мутировать, с единственной целью использовать его в качестве источника для неизменяемой структуры данных...

Я не уверен, почему вы чувствуете, что сохранение этого кеша не имеет смысла. Я также не вижу в этом причин для проблем с производительностью, так как кеш существует только на короткое время, пока выполняется addNewItemToList.

  • 0
    почему вы думаете, что кеш существует только на короткое время? вам нужно будет постоянно хранить копию данных для приложения для любого типа обновления, а затем после каждого обновления вызывать cloneWithRows чтобы создать новую неизменяемую копию.
  • 0
    О, верно, я неправильно прочитал ваш оригинальный пост. Я думаю, что единственный способ сделать это без кеша - это если бы вы могли получить доступ к исходной структуре данных, взятой из источника dataSource , но это не представляется возможным.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню