React Native Navigator routes
<p>I would like to insert in my react-native App a navigation with defined routes. I have found the Navigate.js. Unfortunately, it's not functioning in my app. The following error is indicated:</p>

<p><em>Null is not an object (evaluating 'route.component')</em></p>

<p>I cannot find any mistakes in my code. I do not understand why the object is not defined. However, in the <a href="https://github.com/react-native-material-design/demo-app" rel="nofollow">demo</a> it functions perfectly. Can you please help me? </p>

<p><img src="https://cloud.githubusercontent.com/assets/4801522/15830959/4dae88b0-2c1b-11e6-991f-7f9b8d46730b.png" alt="image"></p>

<p><strong>index.android.js:</strong></p>

<pre><code>import React, { Component } from 'react';
import {
  AppRegistry, Navigator, DrawerLayoutAndroid, ScrollView, View, Text
} from 'react-native';

import Navigate from './src/utils/Navigate';
import Navigation from './src/scenes/Navigation';
import Home from './src/views/Home';

class app extends Component {
  static childContextTypes = {
    drawer: React.PropTypes.object,
    navigator: React.PropTypes.object
  };

  constructor(props) {
    super(props);
    this.state = {
      drawer: null,
      navigator: null
    };
  }

  getChildContext = () =&gt; {
    return {
      drawer: this.state.drawer,
      navigator: this.state.navigator
    }
  };

  setDrawer = (drawer) =&gt; {
    this.setState({
      drawer
    });
  };

  setNavigator = (navigator) =&gt; {
    this.setState({
      navigator: new Navigate(navigator)
    });
  };

  render() {
    const { drawer, navigator } = this.state;
    const navView = React.createElement(Navigation);

    return (
      &lt;DrawerLayoutAndroid
        drawerWidth={300}
        drawerPosition={DrawerLayoutAndroid.positions.Left}
        renderNavigationView={() =&gt; {
                    if (drawer &amp;&amp; navigator) {
                        return navView;
                    }
                    return null;
                }}
        ref={(drawer) =&gt; { !this.state.drawer ? this.setDrawer(drawer) : null }}
      &gt;
        {drawer &amp;&amp;
        &lt;Navigator
          initialRoute={Navigate.getInitialRoute()}
          navigationBar={&lt;Toolbar onIconPress={drawer.openDrawer} /&gt;}
          configureScene={() =&gt; {
                            return Navigator.SceneConfigs.FadeAndroid;
                        }}
          ref={(navigator) =&gt; { !this.state.navigator ? this.setNavigator(navigator) : null }}
          renderScene={(route) =&gt; {
                        if (this.state.navigator &amp;&amp; route.component) {
                            return (
                                &lt;View
                                    style={styles.scene}
                                    showsVerticalScrollIndicator={false}&gt;
                                  &lt;route.component title={route.title} path={route.path} {...route.props} /&gt;
                                &lt;/View&gt;
                            );
                        }
                    }}
        /&gt;
        }
      &lt;/DrawerLayoutAndroid&gt;
    );
  }
}

AppRegistry.registerComponent('app', () =&gt; app);

const styles = {
  scene: {
    flex: 1,
    marginTop: 56
  }
};
</code></pre>

<p><strong>routes.js:</strong></p>

<pre><code>export default {
    home: {
        initialRoute: true,
        title: 'Home',
        component: require('./views/Home').default,
    },

    hotels: {
        title: 'Hotels',
        component: require('./views/Hotels').default
    },

}
</code></pre>

<p><strong><em>./src/utils/Navigate.js :</em></strong></p>

<pre><code>import { BackAndroid } from 'react-native';

let routes = null;

try {
  routes = require('../routes').default;
} catch (e) {
}

export default class Navigate {

  /**
  * Gets the initial root props
  * Accepts a parent route name and finds that routes props
  *    OR - Finds the first parent route with 'initialRoute' set to true.
  *    OR FINALLY - Returns the first parent route.
  * @param path
  * @param customRoutes
  * @returns {{path: *}}
  */
  static getInitialRoute = (path, customRoutes) =&gt; {
    if (customRoutes) {
      routes = customRoutes;
    }
    if (!routes) {
      console.warn(`[Navigate.getInitialRoute()] No routes found. Add routes to src/routes.js.`);
      return null;
    }
    if (path) {
      return {
        path,
        ...routes[path]
      }
    } else {
      let initial;
      for (const route in routes) {
        if (routes[route].initialRoute) {
          initial = {path: route, ...routes[route]};
          break;
        }
      }
      return initial || {
        path,
        ...routes[Object.keys(routes)[0]]
      }
    }
  };

  constructor(navigator) {
    this.navigator = navigator;
    this.savedInstanceStates = new Map();
    this.currentRoute = null;
    this.previousRoute = null;
    this.isChild = false;
    BackAndroid.addEventListener('hardwareBackPress', this._hardwareBackPress);
  }

  /**
  * Generates a pretty name based off the last item in a route path.
  * Mainly for titles
  * @param path
  * @returns {string}
  * @private
  */
  _getPathPrettyName = (path) =&gt; {
    path = path.split('.');
    if (path.length === 1) {
      path = path[0]
    } else {
      path = path[path.length - 1];
    }
    return path.charAt(0).toUpperCase() + path.slice(1);
  };

  /**
  * Handle hardware back press
  * @returns {boolean}
  */
  _hardwareBackPress = () =&gt; {
    if (this.navigator.getCurrentRoutes()[0].path == Navigate.getInitialRoute().path) {
      BackAndroid.exitApp();
      return false;
    } else {
      if (!this.isChild) {
        route = Navigate.getInitialRoute();
        this.currentRoute = route;
        this.navigator.replace(route);
        return true;
      } else {
        this.back();
        return true;
      }
    }
  };

  /**
  * Deep get an object without passing in the 'children' key
  * @param path
  * @returns object
  * @private
  */
  _getRouteObject = (path) =&gt; {
    let obj = routes;
    const properties = path.replace(/\./g, '.children.').split('.');
    if (properties.length === 1) return obj[path];
    properties.forEach(function (key) {
      if (!obj || !hasOwnProperty.call(obj, key)) {
        obj = undefined;
        return;
      }
      obj = obj[key];
    });
    return obj;
  };

  _saveInstanceState = (path, instanceState) =&gt; {
    if (instanceState) {
      this.savedInstanceStates.set(path, instanceState);
    }
  };

  _recoverInstanceState = (path) =&gt; {
    const instanceState = this.savedInstanceStates.get(path);
    if (instanceState) {
      this.savedInstanceStates.delete(path);
    }
    return instanceState || null;
  };
  /**
  * Jump to a component at a certain path defined in routes
  * @param path
  * @param title
  * @param props
  */
  to = (path, title, props) =&gt; {
    if (!path) {
      console.warn(`[Navigate.to(undefined)] A route path is required to navigate to`);
    } else {
      const obj = this._getRouteObject(path);

      if (!obj || !obj.component) {
        console.warn(`[Navigate.to(${path})] No component exists at this path`);
      } else {
        this.isChild = path.split('.').length &gt; 1;
        const route = {
          title: title ? title : (obj.title ? obj.title : path),
          path,
          component: obj.component,
          props
        };
        this.previousRoute = this.currentRoute;
        this.currentRoute = route;
        this.navigator.replace(route);
      }
    }
  };

  /**
  * Go back to the parent of the current component
  * @param title
  * @param props
  */
  back = (title, props) =&gt; {
    const current = this.navigator.getCurrentRoutes()[0].path;
    const path = current.substr(0, current.lastIndexOf('.'));
    const obj = this._getRouteObject(path);
    const savedInstance = this._recoverInstanceState(path); 

    if (!obj) {
      console.warn(`[Navigate.back()] No component exists for the parent of ${current}`);
    } else {
      this.isChild = path.split('.').length &gt; 1;
      const route = {
        // title: title ? title : (obj.title || this._getPathPrettyName(path)),
        title: title ? title : (this.previousRoute ? this.previousRoute.title : (obj.title || this._getPathPrettyName(path))),
        path,
        component: obj.component,
        props
      };

      this.currentRoute = route;
      this.navigator.replace(route);
    }
  };

  /**
  * Go forward to a defined child component of the current route or the first child that exists
  * @param {String} child [Optional] Specify the name of the child to go to.
  * @param {String} title [Optional] Override the routes default title.
  * @param {Object} props [Optional] Send additional props that'll get bootstrapped onto the route
  * @param {Object} savedInstanceState [Optional] Send additional props that'll get bootstrapped onto the route
  */
  forward = (child, title, props, savedInstanceState) =&gt; {
    const current = this.navigator.getCurrentRoutes()[0].path;
    const currentObject = this._getRouteObject(current);

    if (!currentObject.children || !Object.keys(currentObject.children).length) {
      console.warn(`[Navigate.forward()] No child components exists for ${current}`);
    } else {
      this.isChild = true;
      if (child) {
        const obj = this._getRouteObject(`${current}.${child}`);
        if (!obj) {
          console.warn(`[Navigate.forward(${child})] Child component ${child} does not exist on ${current}`);
        } else {
          const route = {
            title: title ? title : (obj.title || this._getPathPrettyName(`${current}.${child}`)),
            path: `${current}.${child}`,
            component: obj.component,
            props
          };
          this.previousRoute = this.currentRoute;
          this.currentRoute = route;
          this.navigator.replace(route);
        }
      } else {
        const path = `${current}.${Object.keys(currentObject.children)[0]}`;
        const obj = this._getRouteObject(path);
        const route = {
          title: title ? title : (obj.title ? obj.title : this._getPathPrettyName(path)),
          path,
          component: obj.component,
          props
        };
        this.currentRoute = route;
        this.navigator.replace(route);
      }
    }
  };

  /**
  * Returns the current route config.
  * @returns {*|makeAction}
  */
  getRoutes = () =&gt; {
    return routes;
  };

  setRoutes = (newRoutes) =&gt; {
    routes = newRoutes;
  };

};
</code></pre>

<p><strong>/src/views/Home.js:</strong></p>

<pre><code>import React from "react";
import {View, StyleSheet, ScrollView, Text} from "react-native";

export class Home extends React.Component {

  static contextTypes = {
    navigator: React.PropTypes.object.isRequired
  };

    render() {
      const { navigator } = this.context;
      const theme = AppStore.getState().theme;

    return &lt;View style={styles.container}&gt;
      &lt;Text&gt;...&lt;/Text&gt;
    &lt;/View&gt;;
  }
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});
</code></pre>