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 Files
Navigation is defined across three main files:- SCREENS.ts: Screen name constants
- ROUTES.ts: Route definitions and URL patterns
- 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
NAVIGATORS.SETTINGS_SPLIT_NAVIGATOR: Account tabNAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR: Workspaces tabNAVIGATORS.REPORTS_SPLIT_NAVIGATOR: Inbox tab
Modal Navigators
- RIGHT_MODAL_NAVIGATOR (RHP): Most common modal for settings/details
- ONBOARDING_MODAL_NAVIGATOR: Onboarding flow
Basic Navigation
Navigating Between Screens
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:Handling Deep Links
Navigation State
Accessing Current Route
Using Navigation State in Components
Multi-Step Flows
For wizards and multi-step forms, use theuseSubPage 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: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:Navigation Testing
Testing Navigation in Components
Testing Route Parameters
Common Patterns
Conditional Navigation
Navigation with Authentication
Navigation with Callback
Troubleshooting
Screen Not Appearing
- Check that the screen is registered in the navigator
- Verify linking config is correct
- Ensure route definition matches the path
- Check TypeScript types are defined
Deep Link Not Working
- Verify route pattern in ROUTES.ts
- Check linking config path matches route
- Test URL format matches expected pattern
- Ensure screen is registered in correct navigator
Back Button Not Working
- Use
Navigation.goBack()with fallback route - Check navigation state has previous screen
- Verify backToRoute is set correctly for deep links
Best Practices
1. Always Use Route Constants
2. Provide Fallback Routes
3. Use TypeScript Types
4. Handle Deep Links
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
