Kastriot Dreshaj
Kastriot Dreshaj

Reputation: 1121

Pass value between component in React Native Navigator

How can I pass data from sceneA to sceneB with Navigator in React Native?

I'm using this to go to sceneB:

this.props.navigator.push({
    id: "MainPage",
    name: 'mainPage'
});

Upvotes: 20

Views: 5808

Answers (6)

Pravin Ghorle
Pravin Ghorle

Reputation: 690

1.While passing the data from scene A to scene B, you must specify in the navigator tag that you are also passing the data with route. ex.

if(route.name == 'home') {
      return <Home navigator={navigator} data={route.data} />
    }

send data from scene A ex.this.props.navigator.push({name:'sceneB',data:{name:this.state.name},});

in scene B access data like this ex. this.props.data.name and you get the data from scene A to scene B

Upvotes: 0

Satish Sojitra
Satish Sojitra

Reputation: 632

You can also pass parameters to sceneA to sceneB using following way. Assume that _handlePressOnClick() is written on some button click in SceneA screen.

_handlePressOnClick(){ //this can be anything
 this.props.navigator.push({
    name: "sceneB", //this is the name which you have defined in _renderScene
    otherData: {
      dataA: "data1"
    }
 })
}

Then defined data in your _renderScene where you have implemented your navigator like this way

_renderScene(route, navigator) {        
    switch(route.name) {
        case "sceneA":
            return (
                <sceneA navigator={navigator} />
            );
        break;
        case "sceneB":
            return (
                <sceneB navigator={navigator} otherData={route.otherData}/>
            );
        break;
  }

Don't forget to import your views files like this

import sceneA from './sceneA';
import sceneB from './sceneB';

Now in sceneB file you can access your otherData following way

var {dataA} = this.props.otherData;

or

constructor(props){
  super(props);
  this.state={
     otherData: this.props.otherData
  }
}

then in your render() method you can access otherData using state.

<Text>{this.state.otherData.dataA}</Text>

You can also use to maintain global level state using redux which is accessible through action and props automatically.

Upvotes: 0

danielfeelfine
danielfeelfine

Reputation: 1884

If you are using react-native-navigation, simply add passProps to your params object, according to documentation.

eg.:

this.props.navigator.push({
  screen: 'example.Screen',
  title: 'Screen Title',
  passProps: {
    id: 'MainPage',
    name: 'mainPage'
  }
})

Upvotes: 0

Nader Dabit
Nader Dabit

Reputation: 53711

You need to set up the passProps property on the navigator. There are a few recent examples on stack overflow, specifically here and here.

<Navigator
  initialRoute={{name: 'Main', component: Main, index: 0}}
  renderScene={(route, navigator) =>    {
    return React.createElement(<YourComponent />, { ...this.props, ...route.passProps, navigator, route } );
  }} />

or

<Navigator
  initialRoute={{name: 'Main', component: Main, index: 0}}
  renderScene={(route, navigator) => {
      <route.component {...route.passProps} navigator={navigator} route={route} />
     }
   }
 />

If you are looking for the most basic of setups just to understand the functionality, I have set up a project here that you can reference, and pasted the code below.

'use strict';

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

class Two extends React.Component {
    render(){
    return(
        <View style={{marginTop:100}}>
          <Text style={{fontSize:20}}>Hello From second component</Text>
          <Text>id: {this.props.id}</Text>
          <Text>name: {this.props.name}</Text>
            <Text>name: {this.props.myVar}</Text>
        </View>
    )
  } 
}

class Main extends React.Component {
  gotoNext(myVar) {
   this.props.navigator.push({
      component: Two,
      passProps: {
        id: 'page_user_infos',
        name: 'page_user_infos',
        myVar: myVar,
      }
    })
  }

  render() {
    return(
      <View style={{flex: 4, flexDirection: 'column', marginTop:100}}>
        <TouchableHighlight style={{ height:40, borderWidth:1, marginBottom:10, backgroundColor: '#ddd'}} name='Pole' onPress={ () => this.gotoNext('This is a property that is being passed') }>
          <Text style={{textAlign:'center'}}>Go to next page</Text>
        </TouchableHighlight>
      </View> 
    )
  }
}

class App extends React.Component {
  render() {

    return (
      <Navigator
                style={{flex:1}}
          initialRoute={{name: 'Main', component: Main, index: 0}}
          renderScene={(route, navigator) =>    {
            if (route.component) {
                          return React.createElement(route.component, { ...this.props, ...route.passProps, navigator, route } );
                      }
                }}
          navigationBar={
            <Navigator.NavigationBar routeMapper={NavigationBarRouteMapper} />
      } />
);
}
}


var NavigationBarRouteMapper = {
  LeftButton(route, navigator, index, navState) {
    if(index > 0) {
      return (
      <TouchableHighlight  style={{marginTop: 10}} onPress={() => {
            if (index > 0) {
              navigator.pop();
            } 
        }}>
       <Text>Back</Text>
     </TouchableHighlight>
 )} else {
 return null}
 },
  RightButton(route, navigator, index, navState) {
    return null;
  },
  Title(route, navigator, index, navState) {
    return null
  }
};


var styles = StyleSheet.create({

});

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

Upvotes: 27

nbkhope
nbkhope

Reputation: 7474

I would set up your navigator as this example. Essentially, put the navigator in your index scene and have all the necessary components imported there. Then, define a renderScene() function to handle all the routes based on a name (or id, like you did). I would not use the component object as the thing itself that is passed from the call to the navigator push method because if you do that you will have to import the component in that specific view. I used to do that and ran into many problems, so I am just warning you if you run into any issues, consider this approach.

  renderScene(route, navigator) {

    if(route.name == 'root') {
      return <Root navigator={navigator} />
    }
    if(route.name == 'register') {
      return <Register navigator={navigator} />
    }
    if(route.name == 'login') {
      return <Login navigator={navigator} />
    }
    if(route.name == 'home') {
      return <Home navigator={navigator} {...route.passProps} />
    }
    if(route.name == 'update') {
      return <Update navigator={navigator} {...route.passProps} />
    }

  }

Upvotes: 4

Ronak Khandelwal
Ronak Khandelwal

Reputation: 311

Sometimes the pass prop doesn't work (at least for me) So what I do is I pass it in the route object itself

nav.push({
        id: 'MainPage',
        name: 'LALA',
        token: tok
      });

so to access it in the next scene I use

var token = this.props.navigator.navigationContext.currentRoute.token;

although kind of a complicated "access" but it is fool proof pass props might work or might not also in this way you can pass the properties in the route object itself thus saving you from the hassle of sending it in a different way.

This might not be the right way but I find it a tad bit more convenient.

Upvotes: 0

Related Questions