Click here to Skip to main content
14,300,760 members

Working on navigation when refactoring a legacy project with React Native

Rate this:
5.00 (1 vote)
Please Sign up or sign in to vote.
5.00 (1 vote)
9 Aug 2019CPOL
This article is dedicated to navigation refactoring in mobile development. It provides examples of common problems, as well as ways to get out of difficult situations related to the work of navigation in mobile development with React Native.


This article is dedicated to navigation refactoring in mobile development. It provides examples of common problems, as well as ways to get out of difficult situations related to the work of navigation in mobile development with React Native.

We will review the main features and problems of a mobile legacy project. Step by step, we will go through a chain of actions concerning problem setting, identifying bottlenecks, finding solutions to existing issues, and obtaining the desired result.

2. Industry

React Native is a relatively new open-source mobile application development platform created by Facebook. It is used to build applications for Android, iOS, and UWP, and allows developers to use React along with the platform’s own capabilities.

Navigation is one of the most important elements in a mobile application. When building your app architecture, pay particular attention to this issue.

The most common libraries for building navigation include:

  • React-Navigation. This is the most popular library, which is often mentioned in the official documentation. Accordingly, it has a lot of stars on GitHub.
  • React-Native-Navigation. This platform uses basic native APIs for iOS and Android. This popular alternative to React-Navigation will suit those who highly appreciate compliance with the platform's agreements and do not care much about customization.

Less common libraries:

  • React-Router-Native. This is an incomplete library. But if you are familiar with the React Router API and have fairly simple requirements for your application, this platform could prove rather helpful.
  • React-Native-Router-Flux. This library is based on React-Navigation but provides another API for interacting with it.

3. Background

I want to tell you briefly about my experience as a developer. I have been working with React Native for more than two years and have published several completed projects in app stores. During this time, I became acquainted with a large number of tools in the React Native environment. Navigation is often a stumbling block in mobile development projects. The legacy project discussed below was no exception. 

4. The Challenge

Code was duplicated in the process of app refactoring instead of dividing the roles into two types (user and administrator). Unfortunately, the same problem was present in navigation.

The architectural features of the application were not taken into account.

All screens were divided into three types: authorization screens, administrator screens, and user screens.

Instead of a logical connection of the Root stack and Tab navigator with role switching, there was an illogical division into navigation stacks based on user roles.

import { SrackNavigator } from 'react-navigation';

import auth from './containers/auth/router';
import accountProf from './containers/accountProf/router';
import accountUser from './containers/accountUser/router';

const stackNavigatorConfig = {
    initialRouteName: 'auth',
    headerMode: 'none',
    navigationOptions: {
        gesturesEnabled: fale

export default StackNavigator({
    auth: {
        screen: auth,
    accountProf: {
        screen: accountProf,
    accountUser: {
        screen: accountUser,
}, stackNavigatorConfig);

And the navigation structure was repeating for each user.

import { StackNavigator } from 'react-navigation';
import { Easing, Animated } from 'reacht-native';

import account from './screens/account';
import create from './screens/create';
import feed from './screens/feed';
import messages from './screens/messages';
import search from './screens/search';
import addPost from './screens/addPost';
import addListing from './screens/addListing';
import locationSearch from './screens/locationSearch';
import listingSearch from './screens/listingSearch';
import createFeed from './screens/createFeed';
import feedPropFeat from './screens/feedPropFeat';
import feedBuildFeat from './screens/feedBuildFeat';
import addOpenHouse from './screens/addOpenHouse';

const stackNavigatorConfig = {initialRouteName: 'account_prof'...};

export default StackNavigator({
    account_prof: {screen: account...},
    accountCreate_prof: {screen: create...},
    accountFeed_prof: {screen: feed...},
    accountSearch_prof: {screen: search...},
    accountMessages_prof: {screen: messages...},
    accountAddPost_prof: {screen: addPost...},
    accountAddOpenHouse_prof: {screen: addOpenHouse...},
    accountAddListing_prof: {screen: addListing...},
    accountLocationSearch: {screen: locationSearch...},
    accountListingSearch_prof: {screen: listingSearch...},
    accountCreateFeed_prof: {screen: createFeed...},
    accountFeedPropFeat_prof: {screen: feedPropFeat...},
    accountFeedBuildFeat_prof: {screen: feedBuildFeat...},
}, stackNavigatorConfig);

I needed to solve the following problems:

  • A general slowdown of the application.
  • Lack of “prerenders” of the main screens, which negatively affected the comfort of users.
  • Navigation did not look native. The transition animations were noticeable and inconvenient to work with.

Check out a screenshot of the modal window component that served as the Tab Navigator:

export default class Navigator extends Component {

    state = {
        active: || '',
        showModal: false
    toggleModal() {
        this.setState( state: {showModal: !this.state.showModal})
    navigateThroughModal(to) {
    render() {
        return (
            <View style={styes.container}>
                    onRequestClose={() => this.setState( state: {showModal: false})}
                    <View style="{styles.modalContainer}>
                <View style="{styles.wrap}>
  • There was an “Overstacking” of screens in the navigation stack, meaning there was no reset (purification). The screens we opened were stored on the stack. Because of this, a memory leak and subsequent emergency shutdown of the application were almost inevitable.

5. The Solution

The outcomes of our work included:

  • Problems related to the optimization of navigation, the lack of a prerender, and the general slowdown was solved by updating the navigation library, using tab navigation, and refusing to use the self-written modal window as a navigator.
  • After refactoring, navigation became more native. Tracking the work of transition animations, as well as prerenders of the main screens on the tabs, made it possible to improve user experience.
  • Navigation was divided into stacks in tab navigation. Transitions were better controlled. We used transitions to the upper level.

The following methods were used for React-Navigation:

  • popToTop - transition to the main screen in the stack;

  • replace - replacing the current route with a new one;

  • reset - clearing the status of the navigator and replacing it, as a result of several actions.

6. Results/Achievements

I was able to eliminate most of the duplicate navigation screens and build a more logical structure.

In the process of refactoring, all navigation was reworked. Part of the work centered around getting rid of double screens and creating a single navigation structure. The screens that were supposed to be located outside the tabs were placed in the root navigator. The screens of the tab navigator itself can be seen in the screenshot below.

const Tab = createBottomTabNavigator({
    accountFeed: {
        screen: feed,
        navigationOptions: () => ({
            tabBarIcon: ({ focused }) => {...},
            tabBarLabl: null
   accountSearch: {
       screen: search,
       navigationOptions: () => ({
           tabBarIcon: ({ focused }) => {...},
           tabBarLabel: null
   accountContent: {
       screen: content,
       navigationOptions: () => ({...}),
   accountMessages: {
       screen: MessageCenterStackNavigator,
       navigationOptions: () => ({...}),
   account: {
       screen: account,
       navigationOptions: () => ({
           tabBarIcon: ({ focused }) => {...},
           tabBarLabel: null
}, config);

export default createStackNavigator({...}, stackNavigatorConfig);

7. Conclusion

Summing up, I would like to once again emphasize the importance of navigation libraries, the use of best practices when working with them, and an in-depth study of technical documentation. Without keeping all this in mind, you will spend a lot of time and effort refactoring and processing an existing project and its codebase.

Choosing a navigation library is an important step in developing your application. Any decision made without careful consideration and caution can damage scalability or lead to other problems.

Useful links:


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Dmitry Kotlyarenko
United States United States
Dmitry Kotlyarenko is a software development engineer at with over 10 years of experience in the niche. His areas of interest include web development, mobile app development for Android and IOS, and automated software testing. He spends much time reading professional literature and writing useful contributor articles for reputable platforms in a developer community.

Comments and Discussions

-- There are no messages in this forum --
Posted 9 Aug 2019


1 bookmarked