2015-04-14 12 views
16

Sto sviluppando una semplice applicazione todo-list utilizzando React Native, il mio problema è il seguente: Ho un NavigatorIOS alla radice del mio progetto, con un componente contenente un ListView come iniziale percorso e un pulsante della barra di navigazione che conduce a una vista di creazione dell'attività.React Native Pass dati tra le visualizzazioni di pari livello

Una volta creata una nuova attività, la vista viene visualizzata in modo che venga visualizzato il ListView. Sto cercando di aggiungere la mia attività appena creata a questo ListView (la sua origine dati è contenuta nello stato del componente).

Come eseguire tale operazione, qual è la buona pratica? Vorrei usare un delegato in pura app nativa ma qui, entrambe le viste sono gestite dall'istanza NavigatorIOS.

index.ios.js

addTask() { 
    console.log("Test"); 
}, 

render() { 
     return (
      <React.NavigatorIOS 
       ref="nav" 
       style={styles.container} 
       tintColor="#ED6063" 
       initialRoute={{ 
        title: "Tasks", 
        component: TasksList, 
        rightButtonTitle: 'Add', 
        onRightButtonPress:() => { 
         this.refs.nav.navigator.push({ 
          title: "New task", 
          component: NewTask, 
          passProps: { 
           onTaskAdded: this.addTask 
          }, 
          leftButtonTitle: "Cancel" 
         }); 
        } 
       }}/> 
     ); 
    } 

NewTask.js

taskAdded() { 
console.log("Added: " + this.state.title + " - " + this.state.description); 
this.props.onTaskAdded({ 
    title: this.state.title, 
    description: this.state.description 
}); 
this.props.navigator.pop(); 
} 

TasksList.js

var dataSource = new ListView.DataSource({ 
    rowHasChanged: (r1, r2) => r1 !== r2 
}); 
this.state = { 
    dataSource: dataSource.cloneWithRows(data) 
}; 

È possibile trovare il complete source code here.

risposta

0

È necessario riscrivere la funzione constructor per ottenere i dati da un modo dinamico. Quindi, quando la pagina si ricarica, otterrebbe dati corretti che includono la nuova attività. Qui ottieni i dati da una matrice statica, che non cambierebbe.

Salvare l'elenco delle attività sul file locale o Firebase e leggere quando costruisci.

+0

Quindi si consiglia di utilizzare una sorta di enorme variabile/area globale per passare i dati tra le viste? Sembra un'architettura pessima ... – Blackus

+0

@Blackus Altrimenti, come si ottiene l'elenco delle attività? "Globale" è facoltativo. – KChen

+0

Che esattamente il punto qui. Durante lo sviluppo nativo, possiamo usare il protocollo o passare blocchi di codice da eseguire (come il callback). Quindi l'elenco delle attività è "condiviso" solo con queste due viste, non è su un grande spazio comune con altre cose. – Blackus

15

La documentazione di React-Native contiene una breve sezione sugli approcci allo communicating between components.

Quando si sta cercando di fare qualcosa di più complicato di un genitore> bambino o bambino-> relazione genitori, ci sono alcune opzioni:

  1. Responsabile modello. Per il vero fratello < -> comunicazioni tra fratelli (vale a dire dove i due fratelli condividono un genitore tramite composizione), puoi avere il genitore che gestisce lo stato. Ad esempio, potresti avere un widget <MyConsole> con uno <TextInput> e uno <ListView> contenenti gli input precedenti di un utente, entrambi sono figli del widget <Console>.

    • Qui, il <Console> può fungere da gestore. Quando il valore <TextInput> modifica il suo valore, è possibile utilizzare l'evento onChangeText per passare il nuovo valore al componente padre <MyConsole>, che quindi aggiorna il suo stato e lo passa ai suoi figli.
  2. Event (publish-subscribe) modello. Ricorda che i componenti sono solo oggetti e quindi puoi utilizzare approcci orientati agli oggetti per comunicare tra i componenti. I documenti React notano che:

    Per la comunicazione tra due componenti che non hanno una relazione genitore-figlio, è possibile impostare il proprio sistema di eventi globale.Iscriviti agli eventi in componentDidMount(), annulla l'iscrizione a componentWillUnmount() e chiama setState() quando ricevi un evento.

    • Qui, è possibile utilizzare una semplice libreria publish-subscribe come pubsub.js in modo che quando un componente cambia solo pubblica il cambiamento e altri componenti correlati può ascoltare per l'evento e aggiornarsi. Questo può essere un approccio molto efficace per le app più piccole.
  3. Modello di flusso. Uno degli svantaggi con un puro sistema di pubblicazione/sottoscrizione è che diventa difficile tenere traccia dello stato. Ad esempio, se hai 2 componenti (ad es. EditTitle, EditBody) che possono aggiornare alcuni stati come un messaggio di posta elettronica, allora un puro sistema di eventi finisce per passare diverse versioni di stato attorno alle quali può diventare disordinato con i conflitti perché non c'è "singolo" versione della verità ". È qui che entra in gioco React's flux approach. Con il flusso, i componenti aggiornano un archivio dati responsabile dell'aggiornamento e della riconciliazione dei dati (ad esempio EmailDataStore) e lo store notifica i componenti dello stato aggiornato.

    • Quindi nel tuo esempio, la visualizzazione delle attività avrebbe emesso un aggiornamento (per esempio tramite la pubblicazione, o una funzione chiamata diretta) ad un TasksDataStore, che potrebbe quindi pubblicare un evento come tasks-updated ai suoi abbonati. Sia il pannello delle attività che il pannello dei risultati sarebbero abbonati all'archivio dati.

Durante l'impostazione di sottoscrizioni, è meglio aggiungere abbonamenti dopo i monti dei componenti e sicuramente rimuoverli prima le smonta componente (altrimenti si finisce con un sacco di abbonamenti orfani).

+0

tks @tohster, hai ragione, impostare un sistema di eventi globale è il modo migliore, ma io sono nuovo per reagire-nativo, non so come rendere un sistema di eventi globale nel nativo del reattivo. – backslash112