Receiving data from a dismissed component using React Navigation

We used the payload bundling capability of react navigation to send the data, However the reverse also possible.

Consider a scenario, Component A launches Component B. In Component B, User types some form entries (TextInput) and press Button titled “Send”, the Component B gets dismissed, Now, The Component A should be able to capture the value entered in Component B.

We can capture that value by sending a function reference of Component A to Component B

Let’s see this in action

Create react native project using $ react-native init MyReceiveNavProj

$ cd MyReceiveNavProj

Add react-navigation and gesture handler and link dependancies

$ npm i --save react-navigation react-native-gesture-handler

Link

$ react-native link react-native-gesture-handler

Create screens folder and create Main.js and Next.js inside

Main.js

import React, { Component } from 'react';
import { Button, View, Text } from 'react-native';

export default class Main extends Component {

    static navigationOptions = {
        title:'Home'
    };

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

    handleValue = (text) => this.setState({textValue:text});

    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text style={{fontSize:18,margin:10}}>{this.state.textValue}</Text>
                <Button title="Click this" onPress={() => { this.props.navigation.navigate('Next',{sendBack:this.handleValue})}}  />
            </View>
        );
    }
}

Notice, onPress action calls this.props.navigation.navigate('Next', {sendBack:this.handleValue}

this.handleValue is a function reference of Component ‘Main’ and it is mapped to a property name sendBack and sent to ‘Next’ Component

In Next.js, write

import React, { Component } from 'react';
import { TextInput, View, Button } from 'react-native';

export default class Next extends Component {
  static navigationOptions = {
    title: 'Next'
  };

  constructor(props){
      super(props)
      this.state = {inputValue:''}
  }

  sendPayloadBack = () => {
    this.props.navigation.state.params.sendBack(this.state.inputValue);
    this.props.navigation.goBack();
  }

  render() {
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <TextInput style={{width:200,height:40,borderWidth:1,borderColor:'blue',borderRadius:4, margin:10}} 
        value={this.state.inputValue} keyboardType='default' onChangeText={(text)=> this.setState({inputValue:text})}
        placeholder="Type here"
        />
        <Button title="Send back" onPress={this.sendPayloadBack}  />
    </View>
    );
  }
}

Here, the this.state.inputValue modified when user starts typing on TextInput, because onChangeText calls this.setState function and duly keeping track of text changes.

The Button onPress calls a function sendPayloadBack, this function is executing following in sequence.

The injected navigation object also has a property params. this can be accessed by this.props.navigation.state.params. This object already carries the payload properties sent from Component ‘Main’

The function handleValue can be accessed in Component ‘Next’ through the property name sendBack bundled in payload

Now calling, this.props.navigation.state.params.sendBack(this.state.inputValue);

This will ensure the state property inputValue sent to ‘Main’ Component through the parameter. And it will execute handleValue function in ‘Main’ Component. Subsequently that will modify state property textValue of Component ‘Main’, This will force render function updated and display in Text

this.props.navigation.goBack(); will force the Component ‘Next’ to be dismissed and bring the previous stack ‘Main’ component to display.

Complete the MyAppNavigator.js and App.js

MyAppNavigator.js

import React, {Component} from 'react';
import {createAppContainer,createStackNavigator} from 'react-navigation';
import Main from './screens/Main';
import Next from './screens/Next';

const Route = createStackNavigator(
    {
        Home:{screen:Main},
        Next:{screen:Next}
    },
    {
        initialRouteName:'Home'
    }
);

const AppContainer = createAppContainer(Route);

export default class MyComponent extends Component{
    render(){
        return <AppContainer/>
    }
}

App.js

import React, {Component} from 'react';
import MyComponent from './MyAppNavigator';

export default class App extends Component {
  render() {
    return <MyComponent/>
  }
}

The concept of StackNavigator and AppContainer have been explained in this example.

Finally execute $ react-native run-android

We get the following output

Now. I hope, we have better control over react navigation. But trivial situation may emerge if i move that ‘Click this’ button on Navigation bar. Also we need to see, How we can build a Login, Logged in views using same app stack strategy. We will discuss them in next section.

Download source code

Leave a Reply

Your email address will not be published. Required fields are marked *