Saturday, October 7, 2017

A simple Custom Drawer Navigation

In the previous sample we built a simple application that has DrawerNavigation. Lets build more on that. In this sample we build a similar DrawerNavigatoer that has a custom list, formatted by our choice

To start, lets have a simple DrawerNavigator, like the following

export const MainNavigator = DrawerNavigator({
  Home: {
    screen: StackNavigator({
      Home: {
        screen: Home,
        navigationOptions:{
          title:'Home',
        }
      },
    })
  },
  Search: {
    screen: StackNavigator({
      Search: {
        screen: Search,
        navigationOptions:{
          title:'Search',
        }
      },
      Result: {
        screen: Result,
        navigationOptions:{
          title:'Result',
        }
      }
    })
  },
  Saved: {
    screen: StackNavigator({
      SavedStack: {
        screen: SavedWord,
        navigationOptions:{
          title:'Saved Word',
        }
      }
    })
  },
  About: {
    screen: StackNavigator({
      AboutStack: {
        screen: About,
        navigationOptions:{
          title:'About',
        }
      }
    })
  },
},{
  contentComponent: props => (<Drawer navigation={props.navigation} drawerProps={{...props}} />),
});



This code is very familiar to us, mostly. What's new though is 'contentComponent'. We have introduced a new component 'Drawer'. That's what is displayed when drawer, opens. What gets displayed in Drawer is left to us. When a user taps on an item in drawer, we need to navigate to respective view. We need navigator object for that. We pass navigator as an attribute to Drawer. We will talk about drawerProps a little later. We have enough to look into Drawer code

drawer.js

export default class Drawer extends Component {
  render() {
    return (
      <ScrollView style={{flex: 1, marginTop:50, marginLeft:10, marginRight: 20,}}>
        <TouchableHighlight style={styles.lineItem} onPress={() => this.props.navigation.navigate('Home')}>
          <Text style={styles.lineItemText}>Home</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.lineItem} onPress={() => this.props.navigation.navigate('Search')}>
          <Text style={styles.lineItemText}>Search</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.lineItem} onPress={() => this.props.navigation.navigate('Saved')} >
          <Text style={styles.lineItemText}>Saved</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.lineItem} onPress={() => this.props.navigation.navigate('About')} >
          <Text style={styles.lineItemText}>About</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.lineItem} onPress={() => this.props.navigation.navigate('PreAuthStack')} >
          <Text style={styles.lineItemText}>LogOff</Text>
        </TouchableHighlight>
      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
  lineItem: {
    borderBottomColor: 'lightgray',
    borderWidth: 1,
    borderTopWidth:0,
    borderLeftWidth:0,
    borderRightWidth:0,
  },
  lineItemText: {
    fontSize: 20,
    fontWeight: '200',
    textAlign: 'center',
    margin: 10,
  },
});

As you see, the code is very simple. Its a basic component that have a scrollview with a list of controls. Simple, right?. All that happens here is we have a bunch of TouchableHighlight controls, when tapped on it, we navigate to respective views.

Our next step is to make this list more dynamic. That's for the next BLOG. If you are interested to try the entire sample, feel free to visit this code here

Thursday, October 5, 2017

More Navigation and Drawer Navigation

With a simple navigation flow using StackNavigator behind us, our next step is to start playing with more advanced navigation. Honestly, from the little experience I got in the industry, "next advanced" level never stops. Needs are insatiable. LoL
From a real world perspective, we have 2 parts for an application, especially on mobile
  1. Pre-authentication flows
  2. Post-authentication flows
We may have modules that need to work before authentication, things like login form, Forgot password, register/signup, contact us, privacy policies, locate us etc. Of course we all know the post authentication flows. Complexity on each side is different. There may be cases where flow is staggered (like MFA flows) while others may be continuous. We can't say which one is more complicated than the other.

With that in mind, lets start to put together an simple flow. This sample will mix a lot of StackNavigation, in addition we will also see DrawerNavigation. One of the most used navigation in mobile world. In other words called "Hamburger menu" or Side navigation.


Here's a high-level view of what we will see

Stack Navigator - App
Stack Stack Navigator - Login
Login form
Forgot Password
Signup
Stack Navigator - Others
Contact us
Privacy policy
Dashboard Navigation
Stack Navigator - Home
Home
Stack Navigator - Module 1
Sub module 1
Sub module 2
Stack Navigator - Module 2
Sub module 1
Sub module 2

At one glance this flow may look simple, but it can be a handful, if we don't understand the concept of navigation from React native context. And trust me, if you go over web, you will see tons of questions around navigation in React native.

As in previous examples, none of the leaf pages are complete. They are place holders pages and contain nothing more than simple text to help us identify the page and a title to show in navigation bar. Our first step is to set the app up. Start by creating a new react-native application and here is the content for our first file

index.js

import { AppRegistry } from 'react-native';
import { StackNavigator } from 'react-navigation';
import React from 'react';
import App from './App';
import LoginNav from './src/screens/preauthentication/authentication/login';
import ForgotPassword from './src/screens/preauthentication/authentication/forgot_password';
import Signup from './src/screens/preauthentication/authentication/signup';
import Home from './src/screens/postauthentication/home';
import { PostAuthDrawer } from "./src/screens/postauthentication/home_drawer";
import ContactUs from "./src/screens/preauthentication/others/contactus";
import PrivacyPolicy from "./src/screens/preauthentication/others/privacy_policy";

const LogonStack = StackNavigator({
  Login: { screen: LoginNav },
  ForgotPassword: { screen: ForgotPassword },
  Signup: { screen: Signup },
}, {
  headerMode: 'screen',
});

const OthersStack = StackNavigator({
  ContactUs: { screen: ContactUs},
  PrivacyPolicy: { screen: PrivacyPolicy},
},{
  headerMode: 'screen',
});

const AppStack = StackNavigator({
  Login: { screen: ({ navigation }) => <LogonStack screenProps={{ rootNavigation: navigation, headerMode: 'none', }} /> },
  Others: { screen: ({ navigation }) => <OthersStack screenProps={{ rootNavigation: navigation, headerMode: 'none', }} /> },
  Home: { screen: PostAuthDrawer }
}, {
  headerMode: 'none'
});

AppRegistry.registerComponent('DrawerNavigation', () => AppStack);

Notice in the above code where in 'Login' and 'Others' item in 'AppStack' have a in-line function that passes the current navigation object as a parameter to 'LogonStack' and 'OthersStack'. We do that, because every stack navigator, as you'd expect has a navigation of its own. Imagine this to be a parent-child navigation. Parent can access the child navigation, because they make it happen. But child has no clue about the parent and hence cannot return back to parent navigation, unless there is a reference to parent some where. The way we pass reference of parent to child is through screenProps. If you are interested and want to know more on the potential of screenProps, please stay tuned. We will have a separate episode on that. Now, why is that we don't have a similar parameter excahnge for 'PostAuthDrawer'. Reason is simple, we don't have anything that will want to come back to 'Login' stack. If we have a log-off screen that's pare of 'Login' stack, yes we will do the same for 'Home' too. Rest of the code is pretty simple

login.js

import React from 'react';
import {
  View,
  Text,
  Button,
  StyleSheet
} from 'react-native';
import { NavigationActions } from 'react-navigation';
import Footer from "../../../components/footer";

export default class LoginNav extends React.Component {
  static navigationOptions = {
    title: 'Login',
  };
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.bodyView}>
          <Text style={styles.text}>PreAuthentication - Login</Text>
          <View>
            <Button title='Login' onPress={ () => this.onLogin() }/>
            <Button title='Cancel' onPress={ () => this.onCancel() } />
            <View>
              <Button title='Forgot Password' onPress={ () => this.onForgotPassword() } />
              <Button title='Signup' onPress={ () => this.onSignup() } />
            </View>
          </View>
        </View>
        <View style={styles.footerView}>
          <Footer screenProps={{rootNavigation: this.props.screenProps.rootNavigation}}/>
        </View>
      </View>);
  }

  onLogin() {
    // go back to main, with additional parameters and NavigationActions
    this.props.screenProps.rootNavigation.dispatch(NavigationActions.reset({
      index: 0,
      actions: [
        NavigationActions.navigate({ routeName: 'Home' })
      ]
    }));

  }

  onCancel() {
    // go back to main with additional parameters and NavigationActions
    this.props.screenProps.rootNavigation.navigate('Main');
  }

  onForgotPassword() {
    console.log('ForgotPassword button pressed');
    this.props.navigation.navigate('ForgotPassword');
  }

  onSignup() {
    console.log('signup button pressed');
    this.props.navigation.navigate('Signup');
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
  },
  bodyView: {
    flex: 1,
    justifyContent: 'center',
    margin: 20,
  },
  footerView: {
    borderColor: 'black',
    borderWidth: 1,
    height: 60,
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});


Here we made a few changes from our previous sample, first off, we introduced a new 'Footer' component. All that a footer offers us is a way to show 'Contact us' and 'Privacy policy' at the bottom of the page. Notice how the navigation is done from within the component. To navigate between 'Forgot password' and 'Signup', we use the regular navigation object. We use rootNavigator that was passed in screenParams to navigate back to parent view/screen. 

Now that 'Footer' is a component within 'Login', navigation boundries are also defined by 'Login' (i.e. 'Forgot Password' and 'Signup'). Hence we are compelled to pass 'rootNavigator' as a parameter to jump outside the current stack. If you remember, both 'Contact Us' and 'Privacy Policy' are defined as a seperate stack and are not part of 'Login' navigator. The only way we can reach 'Others' stack navigator from within 'Login' navigator is to reach the parent navigator, from there communicate with 'Other' navigator. Hope that make sense to you.

I loved writing 'Footer' component. Although, I'd have liked it even more, if I can have in-line style for 'Footer'. It would have been a lot more easier to just add the component and see the result. As opposed to contain Footer in a view and style to view to show up in the bottom.




Footer.js

import React from 'react';
import {
  StyleSheet,
  View,
  Text,
  TouchableOpacity,
  Alert,
} from 'react-native';
import { NavigationActions } from 'react-navigation';

export default class Footer extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <View style={styles.buttonContainer}>
        <TouchableOpacity style={styles.buttons} onPress={() => this.onContactUs()}>
          <Text style={styles.text}>Contact Us</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.buttons} onPress={() => this.onPrivacyPolicy()}>
          <Text style={styles.text}>Privacy Policy</Text>
        </TouchableOpacity>
      </View>);
  }

  onContactUs() {
    console.log('Tapped on Contact Us');
    this.props.screenProps.rootNavigation.dispatch(NavigationActions.navigate({
      routeName: 'Others',
      params: {},
      action: NavigationActions.navigate({ routeName: 'ContactUs'})
    }));
  }

  onPrivacyPolicy() {
    console.log('Tapped on Privacy Policy');
    this.props.screenProps.rootNavigation.dispatch(NavigationActions.navigate({
      routeName: 'Others',
      params: {},
      action: NavigationActions.navigate({ routeName: 'PrivacyPolicy'})
    }));
  }
}

const styles = StyleSheet.create({
  buttonContainer: {
    flex: 1,
    alignItems:'stretch',
    flexDirection: 'row',
    borderWidth: 0,
  },
  buttons: {
    flex:0.5,
    borderWidth: 0,
    borderColor: 'black',
    borderRadius: 5,
    alignSelf: 'stretch',
    marginLeft: 20,
    marginRight:20,
  },
  text: {
    fontSize: 15,
    textAlign: 'center',
    alignSelf:'center',
    textAlignVertical:'center',
    padding:10,
  },
});


Footer is no different from any of the component we built in the past. The only addition here will be the code to navigate. We access the navigator from screenProps and use it. rest of the code is no different from what you have used in the past



forgot_password.js

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

export default class ForgotPassword extends React.Component {
  static navigationOptions = {
    title: 'Forgot Password',
  };
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>PreAuthentication - Forgot Password!!</Text>
        <View>
          <Button title='Submit' onPress={() => this.onSubmit()}/>
          <Button title='Cancel' onPress={() => this.onCancel()}/>
        </View>
      </View>);
  }

  onSubmit() {
    console.log('ForgotPassword - submit button pressed');
  }

  onCancel() {
    console.log('ForgotPassword - submit button pressed');
    this.props.navigation.goBack();
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});


I don't think this code has changed in anyway from our previous examples. Container changes for 'Login' does not affect any navigation in this module. This is the beginning of loosely-coupled navigation.


signup.js

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

export default class Signup extends React.Component {
  static navigationOptions = {
    title: 'Signup',
  };
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>PreAuthentication - Signup</Text>
        <View>
          <Button title='Submit' onPress={() => this.onSubmit()}/>
          <Button title='Cancel' onPress={() => this.onCancel()}/>
        </View>
      </View>);
  }

  onSubmit() {
    console.log('Signup - submit button pressed');
  }

  onCancel() {
    console.log('Signup - submit button pressed');
    this.props.navigation.goBack();
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});


Not much has changed on this code from our previous samples. 


home.js

import React from 'react';
import {
  StyleSheet,
  View,
  Text,
  Button,
  TouchableOpacity,
  Image,
} from 'react-native';

export default class Home extends React.Component {
  static navigationOptions = {
    title: 'Home',
  };

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>Home - Post Login</Text>
      </View>);
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});


This is the landing page post login. If take a step back look into home_drawer.js, we have contained home.js in a seperate stacknavigator in stead of just referencing it as a screen. You can take it as a placeholder to add more in the coming days as well as to cover issues with DrawerNavigator. As I alleged earlier, the most complicated piece in React Native is Navigation. With nested navigators, complication adds up. I'd encourage you to take this code, play around with navigation and experience it for yourself.


submodule_11.js

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

export default class SubModule11 extends React.Component {
  static navigationOptions = {
    title: 'Sub Module 11',
  };
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>Module 1 - Submodule 1</Text>
        <View>
          <Button title='Next' onPress={() => this.onNext() }/>
          <Button title='Home' onPress={() => this.onHome() }/>
        </View>
      </View>);
  }

  onNext() {
    console.log('SubModule11: onNext touched');
    this.props.navigation.navigate('SubModule2')
  }

  onHome() {
    console.log('SubModule11: onHome touched');
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

There is no change to this code from our previous examples. submodule_21 & submodule_22 are the same as submodule_11 & submodule_12


submodule_12.js

import React from 'react';
import {
  StyleSheet,
  View,
  Text,
  Button,
  Alert,
} from 'react-native';
import { NavigationActions } from 'react-navigation';

export default class SubModule12 extends React.Component {
  static navigationOptions = {
    title: 'Sub Module 12',
  };
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>Module 1 - Submodule 2</Text>
        <View>
          <Button title='Next' onPress={() => this.onNext() }/>
          <Button title='Home' onPress={() => this.onHome() }/>
        </View>
      </View>);
  }

  onNext() {
    Alert.alert('Yeah from navigation', "Sorry, can't navigate. Does not exist for the moment", [
        {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
        {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
        {text: 'OK', onPress: () => console.log('OK Pressed')},
      ],
      { cancelable: true });
    console.log('SubModule12: onNext touched');
  }

  onHome() {
    console.dir(this.props);
    this.props.navigation.navigate('Home');
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});



home_drawer.js

import React from 'react';
import { StackNavigator, DrawerNavigator } from 'react-navigation';

import SubModule11 from './module_1/submodule_11';
import SubModule12 from './module_1/submodule_12'
import SubModule21 from './module_2/submodule_21';
import SubModule22 from './module_2/submodule_22'
import Home from './home';

const Module1Stack = StackNavigator({
  SubModule1: { screen: SubModule11 },
  SubModule2: { screen: SubModule12 }
}, {
  headerMode: 'screen'
});

const Module2Stack = StackNavigator({
  SubModule1: { screen: SubModule21 },
  SubModule2: { screen: SubModule22 }
}, {
  headerMode: 'screen'
});

const HomeStack = StackNavigator({
  Home: { screen: Home },
}, {
  headerMode: 'screen',
});

export const PostAuthDrawer = DrawerNavigator({
  Home: { screen: ({ navigation }) => <HomeStack screenProps={{ rootNavigation: navigation, headerMode: 'none', }} /> },
  Module1: {
    screen: Module1Stack,
  },
  Module2: {
    screen: Module2Stack,
  },
});

This code is very much open. Both 'Module1', 'Module2' & 'HomeStack' are simple 'StackNavigator'. All of this navigators are contained in 'DrawerNavigator'. The code for 'Home' is slightly different from the rest. This is one of the bug that I mentioned about React-Native Navigators (v 0.48). Try removing this code and play around to see why this code is there.

In subsequent posts we'll take a look at customization of 'DrawerNavigator'







Monday, October 2, 2017

Basic Navigation in React Native

Navigation is the one of the most important & complicated part of mobile application. This is one piece that we wish to focus more on this and following blogs. The more we understand navigation, better it is for the application.

From day-to-day development, there will always be additions and deletions to navigation and flow pattern's. If navigation is tightly coupled to application, we will have major re-writes for every change to navigation. This in-turn affect release cycle and over all application maintenance cost. For us to stay afloat with eternal changes that comes from BA and business, it is important for us to keep the navigation component out of rest of the application. Keep it as loosely coupled and treat it as seperate library/framework/component. This way, changes can easily be accomodated.

We will build a very basic navigation application now, as we move along, we will add additional functionalites and well as document some lessons learnt, errors and solutions.

Our index file carries nothing more than navigation definition and application level configurations. We want our startup application to kick off from stack navigator, this way we will be able to move forward and back, if/when needed.

index.ios.js/index.android.js
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import { AppRegistry } from 'react-native';
import { StackNavigator } from 'react-navigation';

import Home from './src/screens/postauthentication/home';
import Login from './src/screens/preauthentication/authentication/login';
import ForgotPassword from './src/screens/preauthentication/authentication/forgot_password';
import Signup from './src/screens/preauthentication/authentication/signup';

const PreAuth = StackNavigator({
  Login: { screen: LoginNav },
  ForgotPassword: { screen: ForgotPassword },
  Signup: { screen: Signup },
}, {
  headerMode: 'none'
})

const AppStack = StackNavigator({
  Login: { screen: Login },
  ForgotPassword: { screen: ForgotPassword },
  Signup: { screen: Signup },
});

AppRegistry.registerComponent('MoreNavigation', () => AppStack);

We have not setup the first page/component/form to show up in this navigator. ReactNative and StackNavigator makes it easy for us. It's anybodies guess. Login will be the component that will be displayed by default.

Login component is the main thread that connects to other components like 'Forgot Password' and 'Signup' form. When the user taps on Login button, he'll be redirected to 'Home' component. From a real-world perspective, we can think of this to be login page/form. Upon validation, user should be able to login to the application. While others are options to establish non-authentication flows.

Login.js
/**
 * Sample React Native App - Login.js
 * https://github.com/facebook/react-native
 * @flow
 */
import React from 'react';
import {
  View,
  Text,
  Button,
  StyleSheet
} from 'react-native';
import { NavigationActions } from 'react-navigation';

export default class LoginNav extends React.Component {
  static navigationOptions = {
    title: 'Login',
  };
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>PreAuthentication - Login</Text>
        <View>
          <Button title='Login' onPress={ () => this.onLogin() }/>
          <Button title='Cancel' onPress={ () => this.onCancel() } />
          <View>
            <Button title='Forgot Password' onPress={ () => this.onForgotPassword() } />
            <Button title='Signup' onPress={ () => this.onSignup() } />
          </View>
        </View>
      </View>);
  }

  onLogin() {
    console.log('Login button pressed');
    // go back to main, with additional parameters and NavigationActions
    this.props.navigation.dispatch(NavigationActions.reset({
      index: 0,
      actions: [
        NavigationActions.navigate({ routeName: 'Home' })
      ]
    }));

  }

  onCancel() {
    console.log('Cancel button pressed');
    // go back to main with additional parameters and NavigationActions
    // this.props.navigation.navigate('Main');
  }

  onForgotPassword() {
    console.log('ForgotPassword button pressed');
    this.props.navigation.navigate('ForgotPassword');
  }

  onSignup() {
    console.log('signup button pressed');
    this.props.navigation.navigate('Signup');
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

Notice we have different method implementation for navigation. For us to navigate to 'Forgot Password' or 'Signup' we use props.navigation.navigate. While to go to 'Home', we use NavigationActions. Reason is simple. When we go to 'Home', user should not be able to be able to go back to logon screen unless user log's off. Even worse, post-login we don't want to see a back button in navigation bar for iOS and back button should not take the user to logon screen in Android. This requirement leads us to reset the navigation stack. This way we don't have any history to go back.

Rest of the forms are as simple as login

Signup.js
/**
 * Sample React Native App - Signup.js
 * https://github.com/facebook/react-native
 * @flow
 */
import React from 'react';
import {
  View,
  Text,
  Button,
  StyleSheet
} from 'react-native';

export default class Signup extends React.Component {
  static navigationOptions = {
    title: 'Signup',
  };
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>PreAuthentication - Signup</Text>
        <View>
          <Button title='Submit' onPress={() => this.onSubmit()}/>
          <Button title='Cancel' onPress={() => this.onCancel()}/>
        </View>
      </View>);
  }

  onSubmit() {
    console.log('Signup - submit button pressed');
  }

  onCancel() {
    console.log('Signup - submit button pressed');
    this.props.navigation.goBack();
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

Forgot_password.js
/**
 * Sample React Native App - ForgotPassword.js
 * https://github.com/facebook/react-native
 * @flow
 */
import React from 'react';
import {
  View,
  Text,
  Button,
  StyleSheet,
} from 'react-native';

export default class ForgotPassword extends React.Component {
  static navigationOptions = {
    title: 'Forgot Password',
  };
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text}>PreAuthentication - Forgot Password!!</Text>
        <View>
          <Button title='Submit' onPress={() => this.onSubmit()}/>
          <Button title='Cancel' onPress={() => this.onCancel()}/>
        </View>
      </View>);
  }

  onSubmit() {
    console.log('ForgotPassword - submit button pressed');
  }

  onCancel() {
    console.log('ForgotPassword - submit button pressed');
    this.props.navigation.goBack();
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

Notice, how we go back to previous screen on 'Cancel'. If we are two or more forms down in stack, and wish to go back to root, we can pass a key parameter to 'goBack()'. Check the documentation here for more


That's it for now. A multi-layered navigation application will be added soon