2015-04-05 12 views
19

Uso NavigatorIOS nella mia app nativa reattiva. Voglio passare alcune proprietà quando si ritorna al percorso precedente.Proprietà React Native Pass sul navigatore pop

Un esempio di caso: Sono in una pagina di modulo. Dopo aver inviato i dati, voglio tornare al percorso precedente e fare qualcosa in base ai dati inviati

Come devo fare?

+4

Hai accettato una risposta. Qualche possibilità che ti interessi di condividere un esempio di ciò che hai fatto per aggirare il problema? –

risposta

16

È possibile passare una funzione di richiamata sui puntelli del navigatore quando si preme il nuovo percorso e lo si chiama con i dati del modulo prima di passare al percorso precedente?

+0

Grazie! Funziona – Habibi

+2

E 'possibile darci un esempio di codice come l'hai risolto? Grazie. –

+0

scusate, questo è stato un po '. Ho appena inserito l'oggetto "passProps" quando si sposta il navigatore sulla seconda pagina. Questo oggetto contiene una proprietà di funzione. Nella seconda pagina, posso chiamare quella funzione con this.props. (Nome funzione) – Habibi

18

Esempio di codice che mostra come utilizzare una richiamata prima del pop. Questo è specifico per Navigator e non per NavigatorIOS ma è possibile applicare un codice simile anche per questo.

Hai Pagina1 e Pagina2. Stai spingendo da Pagina1 a Pagina2 e poi ritorni a Pagina1. È necessario passare una funzione di callback da Pagina2 che attiva un codice in Page1 e solo dopo si torna a Pagina1.

In Pagina1 -

_goToPage2: function() { 
    this.props.navigator.push({ 
    component: Page2, 
    sceneConfig: Navigator.SceneConfigs.FloatFromBottom, 
    title: 'hey', 
    callback: this.callbackFunction, 
    }) 
}, 

callbackFunction: function(args) { 
    //do something 
    console.log(args) 
}, 

In Pagina2 -

_backToPage1: function() { 
    this.props.route.callback(args); 
    this.props.navigator.pop(); 
}, 

Il "callbackFunction" funzione verrà chiamata prima di "pop". Per NavigatorIOS dovresti fare lo stesso callback in "passProps". È anche possibile passare argomenti a questo callback. Spero che sia d'aiuto.

+0

Funziona bene. Grazie –

+1

ho ricevuto il messaggio di errore "Impossibile leggere la proprietà 'callback' di undefined". – Allan

+2

@Allan passa il percorso al componente in renderScene. renderScene (router, navigatore) {return } – iou90

1

Per NavigatorIOS è inoltre possibile utilizzare replacePreviousAndPop().

Codice:

'use strict'; 

var React = require('react-native'); 
var { 
    StyleSheet, 
    Text, 
    TouchableOpacity, 
    View, 
    AppRegistry, 
    NavigatorIOS 
} = React; 

var MainApp = React.createClass({ 
    render: function() { 
    return (
     <NavigatorIOS 
      style={styles.mainContainer} 
      initialRoute={{     
      component: FirstScreen, 
      title: 'First Screen', 
      passProps: { text: ' ...' }, 
     }} 
     /> 
    ); 
    }, 
}); 

var FirstScreen = React.createClass({ 
    render: function() { 
    return (
     <View style={styles.container}> 
     <Text style={styles.helloText}> 
       Hello {this.props.text} 
     </Text> 
     <TouchableOpacity 
      style={styles.changeButton} onPress={this.gotoSecondScreen}> 
      <Text>Click to change</Text> 
     </TouchableOpacity>  
     </View> 
    ); 
    }, 
    gotoSecondScreen: function() { 
     console.log("button pressed"); 
    this.props.navigator.push({ 
     title: "Second Screen", 
     component: SecondScreen 
    }); 
    }, 
}); 

var SecondScreen = React.createClass({ 
    render: function() {  
    return (
     <View style={styles.container}> 
     <Text style={styles.helloText}> 
      Select a greeting 
     </Text> 
     <TouchableOpacity 
      style={styles.changeButton} onPress={() => this.sayHello("World!")}> 
      <Text>...World!</Text> 
     </TouchableOpacity> 
     <TouchableOpacity 
      style={styles.changeButton} onPress={() => this.sayHello("my Friend!")}> 
      <Text>...my Friend!</Text> 
     </TouchableOpacity> 
     </View> 
    ); 
    }, 
    sayHello: function(greeting) { 
     console.log("world button pressed"); 
    this.props.navigator.replacePreviousAndPop({ 
     title: "First Screen", 
     component: FirstScreen, 
     passProps: {text: greeting} 
    }); 
    } 
}); 


var styles = StyleSheet.create({ 
    mainContainer: { 
     flex: 1, 
     backgroundColor: "#eee" 
    }, 
    container: { 
    flex: 1, 
    alignItems: "center", 
    justifyContent: "center", 
    marginTop: 50,  
    }, 
    helloText: { 
    fontSize: 16, 
    }, 
    changeButton: { 
    padding: 5, 
    borderWidth: 1, 
    borderColor: "blue", 
    borderRadius: 4, 
    marginTop: 20 
    } 
}); 



AppRegistry.registerComponent("TestApp",() => MainApp); 

È possibile trovare l'esempio di lavoro qui: https://rnplay.org/apps/JPWaPQ

Mi auguro che aiuta!

+0

Insieme all'aggiunta di collegamenti esterni, è necessario fornire una descrizione di tale risposta in quanto è probabile che i collegamenti esterni cambino e la risposta non sarà più utile. – tomab

+0

Grazie per il tuo consiglio @tomab. Ho modificato la mia risposta. – andreaswienes

1

Ho avuto lo stesso problema con il navigatore di React Native che sono riuscito a risolvere utilizzando EventEmitters e Subscribables. Questo esempio è stato molto utile: https://colinramsay.co.uk/2015/07/04/react-native-eventemitters.html

Tutto quello che dovevo fare era aggiornare per ES6 e l'ultima versione di React Native.

livello superiore dell'app:

import React, { Component } from 'react'; 
import {AppRegistry} from 'react-native'; 
import {MyNavigator} from './components/MyNavigator'; 
import EventEmitter from 'EventEmitter'; 
import Subscribable from 'Subscribable'; 

class MyApp extends Component { 
    constructor(props) { 
     super(props); 
    } 
    componentWillMount() { 
     this.eventEmitter = new EventEmitter(); 
    } 
    render() { 
    return (<MyNavigator events={this.eventEmitter}/>); 
    } 
} 

AppRegistry.registerComponent('MyApp',() => MyApp); 

Nella funzione _renderScene del vostro navigatore, assicuratevi di includere il puntello "eventi":

_renderScene(route, navigator) { 
    var Component = route.component; 
    return (
     <Component {...route.props} navigator={navigator} route={route} events={this.props.events} /> 
    ); 
} 

E qui è il codice per la FooScreen Componente che esegue il rendering di un elenco.

(Si noti che react-mixin è stato utilizzato qui per sottoscrivere l'evento Nella maggior parte dei casi mixins should be eschewed a favore di componenti di ordine superiore, ma non riuscivo a trovare un modo per aggirare in questo caso.):

import React, { Component } from 'react'; 
import { 
    StyleSheet, 
    View, 
    ListView, 
    Text 
} from 'react-native'; 
import {ListItemForFoo} from './ListItemForFoo'; 
import reactMixin from 'react-mixin' 
import Subscribable from 'Subscribable'; 

export class FooScreen extends Component { 
    constructor(props) { 
    super(props); 

    this._refreshData = this._refreshData.bind(this); 
    this._renderRow = this._renderRow.bind(this); 

    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); 

    this.state = { 
     dataSource: ds.cloneWithRows([]) 
    } 
    } 

    componentDidMount(){ 
    //This is the code that listens for a "FooSaved" event. 
    this.addListenerOn(this.props.events, 'FooSaved', this._refreshData); 
    this._refreshData(); 
    } 

    _refreshData(){ 
    this.setState({ 
     dataSource: this.state.dataSource.cloneWithRows(//YOUR DATASOURCE GOES HERE) 
    }) 
    } 
    _renderRow(rowData){ 
     return <ListItemForFoo 
      foo={rowData} 
      navigator={this.props.navigator} />; 
    } 
    render(){ 
    return(
     <ListView 
     dataSource={this.state.dataSource} 
     renderRow={this._renderRow} 
     /> 
    ) 

    } 
} 
reactMixin(FooScreen.prototype, Subscribable.Mixin); 

Infine.Abbiamo bisogno di emettere in realtà che evento dopo il salvataggio di una Foo:

Nella tua NewFooForm.js componente si dovrebbe avere un metodo come questo:

_onPressButton(){ 
    //Some code that saves your Foo 

    this.props.events.emit('FooSaved'); //emit the event 
    this.props.navigator.pop(); //Pop back to your ListView component 
    } 
1

È possibile utilizzare AsyncStorage, risparmiare un po 'sul valore dei componenti del bambino e quindi chiamare navigator.pop():

AsyncStorage.setItem('postsReload','true'); 
this.props.navigator.pop(); 

In componente principale si può leggere da AsyncStorage:

async componentWillReceiveProps(nextProps) { 
    const reload = await AsyncStorage.getItem('postsReload'); 
    if (reload && reload=='true') 
    { 
     AsyncStorage.setItem('postsReload','false'); 
     //do something 
    } 
    }