Skip to content

Ajith-Pandian/ReactNavigationUtils

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React Navigation Utils

Utility functions for react-navigation library

npm npm npm code style: prettier PRs Welcome

Usage

Install:

npm install --save react-navigation-utils

or

yarn add react-navigation-utils

Integration Guide:

1. withHeader(Screen, renderHeader) : renders custom header for StackNavigator

Params Type Description
Screen Component The screen to have header
renderHeader(props) Callback Callback that accepts props returns header.
props : {navigation: {…}, screenProps: {…}, navigationOptions: {…}}
header : Valid ReactComponent
import React, { Component } from "react";
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
import { StackNavigator } from "react-navigation";
import { withHeader } from "react-navigation-utils";

const FirstScreen = props => (
  <View style={styles.sContainer}>
    <Text>This is FirstScreen</Text>
    <TouchableOpacity
      onPress={() => props.navigation.navigate("SecondScreen", { data: "Hi" })}
    >
      <Text>Open SecondScreen</Text>
    </TouchableOpacity>
  </View>
);

let FirstScreenWithHeader = withHeader(FirstScreen, () => (
  <Text style={styles.sHeaderStyle}>This is Custom Header 1</Text>
));

class SecondScreen extends Component {
  render() {
    return (
      <View style={styles.sContainer}>
        <Text>This is SecondScreen</Text>
      </View>
    );
  }
}

let SecondScreenWithHeader = withHeader(SecondScreen, props => {
  let data = props.navigation.state.params.data;
  return (
    <Text style={styles.sHeaderStyle}>
      This is Custom Header 2 with data {data}
    </Text>
  );
});

const App = StackNavigator({
  FirstScreen: { screen: FirstScreenWithHeader },
  SecondScreen: { screen: SecondScreenWithHeader }
});

export default App;

const styles = StyleSheet.create({
  sContainer: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#F5FCFF"
  },
  sHeaderStyle: { margin: 10 }
});

2. withHeaderAndClassProps(Screen, renderHeader) : renders custom header for StackNavigator

Params Type Description
Screen Component The screen to have header (** must be a class** )
renderHeader(props) Callback Callback that accepts props returns header.
props : {navigation: {…}, screenProps: {…}, navigationOptions: {…}}
props.navigation.state.params will have classProps & classMethods
classProps: All props passed to the Screen Component
classMethods: All binded methods from Screen Component
header : Valid ReactComponent
import React, { Component } from "react";
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  ToastAndroid
} from "react-native";
import { StackNavigator } from "react-navigation";

import {
  withHeader,
  withHeaderAndClassProps,
  getNestedObject,
  CLASS_PROPS,
  CLASS_METHODS
} from "react-navigation-utils";

const FirstScreen = props => (
  <View style={styles.sContainer}>
    <Text>{`I'm FirstScreen`}</Text>
    <TouchableOpacity onPress={() => props.navigation.navigate("Second")}>
      <Text style={{ margin: 10 }}>Open Second</Text>
    </TouchableOpacity>
  </View>
);

let FirstWithHeader = withHeader(FirstScreen, () => (
  <Text style={{ margin: 10, textAlign: "center" }}>This is header</Text>
));

class SecondScreen extends Component {
  constructor() {
    super();
    this.handleBackClick = this.handleBackClick.bind(this);
  }
  handleBackPress = () => {
    /* arrowFunctionBindedMethod */
    ToastAndroid.show("Back Pressed", ToastAndroid.SHORT);
    this.props.navigation.goBack();
  };
  handleBackClick() {
    /* constructorBindedMethod */
    ToastAndroid.show("Back Clicked", ToastAndroid.SHORT);
    this.props.navigation.goBack();
  }
  render() {
    return (
      <View style={styles.sContainer}>
        <Text>{`I'm SecondScreen`}</Text>
      </View>
    );
  }
}

let SecondWithHeader = withHeaderAndClassProps(SecondScreen, props => {
  /* props.navigation.state.params.classProps will have all props of SecondScreen */
  /* getNestedObject(props,path)- helper method to extract nested classProps object if path is valid */
  /* CLASS_PROPS is a type for  props.navigation.state.params.classProps */
  let classProps = getNestedObject(props, CLASS_PROPS);
  /* classProps will contain all props passed to SecondScreen */

  /* props.navigation.state.params.classMethods will have all binded methods of SecondScreen */
  /* getNestedObject(props,path)- helper method to extract nested classProps object if path is valid */
  /* CLASS_METHODS is a type for  props.navigation.state.params.classMethods */
  let classMethods = getNestedObject(props, CLASS_METHODS);
  /* classMethods will contain {handleBackPress: ƒ, handleBackClick: ƒ} */

  return (
    <View
      style={{
        alignItems: "center",
        justifyContent: "center"
      }}
    >
      <Text style={{ margin: 5 }}>Header with classProps and classMethods</Text>
      <TouchableOpacity
        onPress={() => (classMethods ? classMethods.handleBackPress() : null)}
        style={{ margin: 5 }}
      >
        <Text>Press Me !</Text>
      </TouchableOpacity>
      <TouchableOpacity
        onPress={() => (classMethods ? classMethods.handleBackClick() : null)}
        style={{ margin: 5 }}
      >
        <Text>Click Me !</Text>
      </TouchableOpacity>
    </View>
  );
});

const App = StackNavigator({
  First: { screen: FirstWithHeader },
  Second: { screen: SecondWithHeader }
});

export default App;

const styles = StyleSheet.create({
  sContainer: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#F5FCFF"
  }
});

3. LazyLoading : To implement LazyLoading on TabNavigator following steps should be followed

  • withLazyLoading(Screen) : implements lazy loading on TabNavigator screen
Params Type Description
ScreenComponent Component The component to be lazy loaded
  • handleLazyLoading(navigation,props) : handles tabBarOnPress events to enable LazyLoading
Params Type Description
navigation NavigationProp Navigation property obtained from Navigator via navigationOptions
props Props Props obtained from tabBarOnPress on Navigator

NOTE:

  • firstRoute (the first screen on TabNavigator) or initialRoute should not have lazy loading. They should be rendered normally.

  • If first screen has LazyLoading, nothing will be rendered.

import React, { Component } from "react";
import { View, Text, StyleSheet } from "react-native";
import { TabNavigator } from "react-navigation";
import { withLazyLoading, handleLazyLoading } from "react-navigation-utils";

const TabScreen1 = () => {
  /* uncomment below line to check lazy loading */
  // console.log("rendered 1");
  return (
    <View style={styles.sContainer}>
      <Text>Im first tab</Text>
    </View>
  );
};

const TabScreen2 = () => {
  /* uncomment below line to check lazy loading */
  // console.log("rendered 2");
  return (
    <View style={styles.sContainer}>
      <Text>Im second tab</Text>
    </View>
  );
};

const LazyTabScreen2 = withLazyLoading(TabScreen2);

const MyTabs = TabNavigator(
  {
    tab1: { screen: TabScreen1 } /* No LazyLoad on 1st route */,
    tab2: { screen: LazyTabScreen2 }
  },
  {
    navigationOptions: ({ navigation }) => ({
      tabBarOnPress: props => handleLazyLoading(navigation, props)
    })
  }
);

export default MyTabs;

const styles = StyleSheet.create({
  sContainer: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center"
  }
});

4. resetNavigationToFirst(routeName, navigationProp) : resets the stack to start with passed route

Params Type Description
routeName String The route to be reset as first
navigationProp Navigation Property Navigation property obtained from Navigator
import React, { Component } from "react";
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
import { StackNavigator } from "react-navigation";
import { resetNavigationToFirst } from "react-navigation-utils";

const FirstScreen = props => (
  <View style={styles.sContainer}>
    <Text>This is FirstScreen</Text>
    <TouchableOpacity
      onPress={() => resetNavigationToFirst("SecondScreen", props.navigation)}
    >
      <Text>Open SecondScreen</Text>
    </TouchableOpacity>
  </View>
);

class SecondScreen extends Component {
  render() {
    return (
      <View style={styles.sContainer}>
        <Text>This is SecondScreen</Text>
      </View>
    );
  }
}

const App = StackNavigator(
  {
    FirstScreen: { screen: FirstScreen },
    SecondScreen: { screen: SecondScreen }
  },
  {
    navigationOptions: {
      title: "App"
    }
  }
);

export default App;

const styles = StyleSheet.create({
  sContainer: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#F5FCFF"
  },
  sHeaderStyle: { margin: 10 }
});

About

Utility functions for react-navigation library

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published