Я делаю простую реакцию родного приложения, имеющего несколько списков, и дает пользователю возможность обновить элемент в любом из этих списков или добавить новые элементы в список.
Однако, как ранее указывалось на 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
}
}
Вам нужно будет сохранить предыдущие элементы, если вы хотите отменить оптимистичное обновление. Для этого вам нужно будет "кэшировать" или хранить ссылку на предыдущие данные.
Вы можете оптимизировать вызов 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)
});
});
}
Нет, я уверен, что нет никакого другого способа обновить источник данных ListView, поскольку, как вы объясните, он неизменен. Неизменность подразумевает, что вам всегда нужно будет сделать копию чего-либо, прежде чем добавлять к ней.
Вы упомянули:
Однако, похоже, не имеет смысла хранить кэш структуры данных, с которой я могу мутировать, с единственной целью использовать его в качестве источника для неизменяемой структуры данных...
Я не уверен, почему вы чувствуете, что сохранение этого кеша не имеет смысла. Я также не вижу в этом причин для проблем с производительностью, так как кеш существует только на короткое время, пока выполняется addNewItemToList
.
cloneWithRows
чтобы создать новую неизменяемую копию.dataSource
, но это не представляется возможным.