2016-02-26 7 views
7

Sto realizzando una semplice app nativa che ha diversi elenchi e offre all'utente la possibilità di aggiornare un elemento in uno di questi elenchi o di aggiungere nuovi elementi all'elenco.Come aggiornare ottimisticamente l'elemento in un ListView

Tuttavia, come è stato precedentemente indicato su StackOverflow, non è possibile aggiungere o inviare un elemento a un ListView perché si suppone che sia una struttura di dati immutabile. vale a dire in questo codice non si può spingere un nuovo elemento nella sorgente di dati

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 

Quindi quello che ho fatto, invece è quello di mantenere una copia (this.state.items; nel codice qui sotto) dei dati vado a prendere dal server (e che Chiamo cloneWithRows su), aggiungo a quella copia (o lo aggiorno se si tratta di una modifica), quindi chiamo cloneWithRows sulla copia modificata ogni volta che c'è una modifica (tramite una modifica o creazione di un nuovo elemento) e aggiorni l'interfaccia utente, e quindi aggiorna il server (quest'ultima parte non rientra nell'ambito dell'applicazione react nativa). Quindi, in sintesi, ho una copia dei dati che posso modificare per utilizzare come fonte di dati per ds.cloneWithRows quando apporto una modifica

Tuttavia, non sembra avere molto senso mantenere una cache della struttura dati che posso mutare al solo scopo di usarla come sorgente per la struttura dei dati immutabile (listForUI: ds.cloneWithRows(t) nel codice qui sotto) se voglio aggiornare ottimisticamente l'interfaccia utente (es mostra la modifica prima che sia salvata sul server).

L'alternativa (anche se non ha molto senso per me) sembra essere quella di aggiornare il server e attendere una risposta (senza tenere una cache di alcun tipo) ogni volta che aggiorno o aggiungo un nuovo elemento alla mia lista , ma sarebbe lento?

Domanda: A parte conservare una copia mutabile dei dati come cache, esiste un modo per aggiornare in modo ottimistico un interfaccia utente in risposta nativo?

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 
    } 

} 

risposta

1

No, sono abbastanza sicuro che non ci sia altro modo per aggiornare un DataSource ListView, poiché, come si spiega, è immutabile. L'immutabilità implica che avrai sempre bisogno di fare una copia di qualsiasi cosa prima di aggiungerla.

si parla:

Tuttavia, non sembra avere molto senso per mantenere una cache della struttura dati che posso mutare per il solo scopo di usarlo come fonte per i dati immutabili struttura ...

Non sono proprio sicuro del motivo per cui ritenete che mantenere questo cache non abbia senso. Non vedo nemmeno che sia causa di problemi di prestazioni, poiché la cache esiste solo per un breve momento mentre è in esecuzione addNewItemToList.

+0

perché pensi che la cache esista solo per un breve momento? dovresti tenere una copia dei dati per l'app in ogni momento per qualsiasi tipo di aggiornamento, e quindi dopo ogni aggiornamento chiama 'cloneWithRows' per creare la nuova copia immutabile. – Leahcim

+0

Oh, giusto, avevo letto male il tuo post originale. Penso che l'unico modo in cui ciò sarebbe possibile, senza cache, sarebbe se tu fossi in grado di accedere alla struttura dei dati originale rimossa da 'dataSource', ma ciò non sembra possibile. –

1

È necessario memorizzare gli elementi precedenti se si desidera annullare un aggiornamento ottimistico. Per fare ciò è necessario "memorizzare" o memorizzare un riferimento ai dati precedenti in qualche modo.

È ottimisticamente possibile chiamare this.setState nel vostro addNewItemToList gestore e aggiornare il tuo stato (causando un re-rendering), e quindi nel vostro fetch è possibile ripristinare il cambiamento, se necessario (ad esempio se la chiamata non riesce):

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