Skip to main content

Overview

New Expensify uses React Navigation with custom navigators and deep linking to provide a seamless cross-platform navigation experience. The navigation system is designed to work identically on iOS, Android, Web, and Desktop.
For the complete navigation documentation, see contributingGuides/NAVIGATION.md in the repository.

Core Concepts

Navigation is defined across three main files:
  1. SCREENS.ts: Screen name constants
  2. ROUTES.ts: Route definitions and URL patterns
  3. NAVIGATORS.ts: Navigator name constants

Key Navigators

RootStackNavigator

The top-level navigator that manages the main navigation stack.

SplitNavigator

Custom navigator for wide screens with sidebar and central pane:
  • LHN (Left Hand Navigation): Report list on the left
  • Central Pane: Main content area
  • RHP (Right Hand Panel): Settings and detail panels
Examples:
  • NAVIGATORS.SETTINGS_SPLIT_NAVIGATOR: Account tab
  • NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR: Workspaces tab
  • NAVIGATORS.REPORTS_SPLIT_NAVIGATOR: Inbox tab
  • RIGHT_MODAL_NAVIGATOR (RHP): Most common modal for settings/details
  • ONBOARDING_MODAL_NAVIGATOR: Onboarding flow

Basic Navigation

Going Back

Dismissing Modals

Defining Routes

Static Routes

Simple routes without parameters:

Dynamic Routes

Routes with parameters:

Adding a New Screen

Step 1: Define Screen Name

Step 2: Define Route

Step 3: Configure Linking

Step 4: Define TypeScript Types

Step 5: Create Screen Component

Step 6: Register in Navigator

Deep Linking

New Expensify supports deep linking for all screens:
The navigation state is automatically reconstructed from the URL.

Accessing Current Route

Using Navigation State in Components

Multi-Step Flows

For wizards and multi-step forms, use the useSubPage hook:

RHP (Right Hand Panel)

When to Use RHP

Use RHP for:
  • Settings screens
  • Detail views
  • Edit forms
  • Secondary flows

Setting Underlay Screen

Configure which screen appears underneath RHP:
When opening DISPLAY_NAME in RHP, PROFILE.ROOT will show underneath.

Performance Optimizations

The navigation system includes several performance optimizations:

1. Limited Screen Mounting

Only the last 2 screens in the stack are mounted to reduce memory usage.

2. Preserved State

Unmounted screen state is preserved and restored when navigating back.

3. Session Storage

Last visited paths are saved to session storage for page refresh persistence:

Testing Navigation in Components

Testing Route Parameters

Common Patterns

Conditional Navigation

Troubleshooting

Screen Not Appearing

  1. Check that the screen is registered in the navigator
  2. Verify linking config is correct
  3. Ensure route definition matches the path
  4. Check TypeScript types are defined
  1. Verify route pattern in ROUTES.ts
  2. Check linking config path matches route
  3. Test URL format matches expected pattern
  4. Ensure screen is registered in correct navigator

Back Button Not Working

  1. Use Navigation.goBack() with fallback route
  2. Check navigation state has previous screen
  3. Verify backToRoute is set correctly for deep links

Best Practices

1. Always Use Route Constants

2. Provide Fallback Routes

3. Use TypeScript Types

Ensure screens work when opened directly via URL.

Next Steps

Offline-First

Understand offline navigation patterns

Testing

Test navigation flows

API Integration

Navigate after API calls

Full Navigation Guide

Complete navigation documentation