Skip to main content

Overview

New Expensify uses React Native to deliver a native experience on iOS, Android, and Web from a single codebase. This guide covers the React Native-specific aspects of the architecture.

React Native Version

The app uses the latest stable version of React Native with the New Architecture enabled:
  • Fabric Renderer: New rendering system
  • TurboModules: Improved native module integration
  • Hermes: JavaScript engine optimized for React Native

Platform Support

All features must work on iOS, Android, Web, mWeb (mobile web), and macOS.

Platform-Specific Code

When platform-specific code is necessary, use the Platform module:

File Extensions for Platform-Specific Files

React Native automatically loads the correct file based on the platform.

Component Structure

Base Components

New Expensify has custom wrappers for many React Native primitives in src/components/:
Why custom components?
  • Consistent styling across the app
  • Accessibility built-in
  • Performance optimizations
  • Type safety

Screen Wrapper

All page components should use ScreenWrapper:
ScreenWrapper provides:
  • Safe area handling
  • Keyboard avoiding behavior
  • Scroll view when needed
  • Loading states
  • Offline indicators

Styling

Theme System

All styles use the centralized theme:

StyleSheet

Always use StyleSheet.create() for performance:

Responsive Design

Use the responsive layout hook:

Performance Best Practices

1. Memoization

2. FlashList for Long Lists

Use FlashList instead of FlatList for better performance:

3. Avoid Inline Functions and Styles

Native Modules

Using Native Modules

When React Native APIs aren’t sufficient, use native modules:

Platform-Specific Modules

New Expensify uses React Navigation. See Navigation System for details.

Basic Navigation Example

Accessibility

All components must be accessible:

Accessibility Properties

  • accessible: Groups children for screen readers
  • accessibilityLabel: Description read by screen readers
  • accessibilityHint: Additional context
  • accessibilityRole: Semantic role (button, link, header, etc.)
  • accessibilityState: Current state (disabled, selected, etc.)

Internationalization (i18n)

All user-facing strings must be translated:
Translation files are in src/languages/:
  • en.ts - English
  • es.ts - Spanish
  • etc.

Image Handling

Static Images

Remote Images

Keyboard Handling

Testing React Native Components

Common Pitfalls

1. Not Testing on All Platforms

Always test your changes on iOS, Android, Web, and mobile web before submitting a PR.

2. Hardcoded Colors/Sizes

3. Missing Keys in Lists

4. Not Handling Offline State

See Offline-First Architecture for proper offline handling.

Device-Specific Features

Camera Access

Location Services

Push Notifications

Push notifications are handled via Urban Airship (Airship):

Debugging

React Native Debugger

Flipper

Flipper is enabled for React Native debugging:
  • Network inspector
  • Layout inspector
  • Redux/Onyx state
  • Performance metrics

Build Commands

Next Steps

State Management

Learn about Onyx state management

Navigation

Understand navigation patterns

Testing

Write tests for React Native components

Best Practices

Follow React Native best practices