|
| 1 | +--- |
| 2 | +name: rnn-codebase |
| 3 | +description: Navigate and work with the react-native-navigation (RNN) codebase. Use when fixing bugs, adding features, tracing command flows, understanding options resolution, or working across JS/iOS/Android layers in this repo. |
| 4 | +--- |
| 5 | + |
| 6 | +# React Native Navigation Codebase |
| 7 | + |
| 8 | +## Architecture Overview |
| 9 | + |
| 10 | +RNN has three layers that mirror each other: |
| 11 | + |
| 12 | +``` |
| 13 | +JS/TS (src/) → TurboModule bridge → iOS native (ios/) |
| 14 | + → Android native (android/) |
| 15 | +``` |
| 16 | + |
| 17 | +A navigation command (e.g. `push`) flows: |
| 18 | +1. `Navigation.push()` → `Commands.ts` → processing pipeline → `NativeCommandsSender.ts` |
| 19 | +2. TurboModule: `RNNTurboModule` (iOS) / `NavigationTurboModule.kt` (Android) |
| 20 | +3. iOS: `RNNCommandsHandler` → `RNNViewControllerFactory` → UIKit controllers |
| 21 | +4. Android: `Navigator` → `LayoutFactory` → View-based controllers (no Fragments) |
| 22 | + |
| 23 | +Read [ARCHITECTURE.md](../../ARCHITECTURE.md) for the full overview. |
| 24 | + |
| 25 | +## Key Cross-Layer Mappings |
| 26 | + |
| 27 | +### Layout Types → Native Controllers |
| 28 | + |
| 29 | +| JS Layout Type | iOS Controller | Android Controller | |
| 30 | +|----------------|---------------|-------------------| |
| 31 | +| `component` | `RNNComponentViewController` | `ComponentViewController` | |
| 32 | +| `stack` | `RNNStackController` (UINavigationController) | `StackController` | |
| 33 | +| `bottomTabs` | `RNNBottomTabsController` (UITabBarController) | `BottomTabsController` | |
| 34 | +| `sideMenu` | `RNNSideMenuViewController` (MMDrawerController) | `SideMenuController` (DrawerLayout) | |
| 35 | +| `topTabs` | `RNNTopTabsViewController` | `TopTabsController` (ViewPager) | |
| 36 | +| `splitView` | `RNNSplitViewController` | N/A (iOS only) | |
| 37 | +| `externalComponent` | `RNNExternalViewController` | `ExternalComponentViewController` | |
| 38 | + |
| 39 | +### Options → Presenters |
| 40 | + |
| 41 | +Each controller type has a Presenter that applies options to views: |
| 42 | + |
| 43 | +| iOS Controller | iOS Presenter | Android Presenter | |
| 44 | +|----------------|--------------|-------------------| |
| 45 | +| `RNNComponentViewController` | `RNNComponentPresenter` | `ComponentPresenter` | |
| 46 | +| `RNNStackController` | `RNNStackPresenter` + `TopBarPresenter` | `StackPresenter` | |
| 47 | +| `RNNBottomTabsController` | `RNNBottomTabsPresenter` | `BottomTabsPresenter` | |
| 48 | +| `RNNSideMenuViewController` | `RNNSideMenuPresenter` | `SideMenuPresenter` | |
| 49 | + |
| 50 | +### Events (same names both platforms) |
| 51 | + |
| 52 | +| Event | Trigger | |
| 53 | +|-------|---------| |
| 54 | +| `RNN.ComponentDidAppear` | Screen becomes visible | |
| 55 | +| `RNN.ComponentDidDisappear` | Screen hidden | |
| 56 | +| `RNN.NavigationButtonPressed` | TopBar button tap | |
| 57 | +| `RNN.BottomTabSelected` | Tab changed | |
| 58 | +| `RNN.ModalDismissed` | Modal dismissed | |
| 59 | +| `RNN.ScreenPopped` | Screen popped from stack | |
| 60 | +| `RNN.CommandCompleted` | Any command finished | |
| 61 | + |
| 62 | +## Where to Find Things |
| 63 | + |
| 64 | +### By task: "I need to fix/change X" |
| 65 | + |
| 66 | +| Task | JS File(s) | iOS File(s) | Android File(s) | |
| 67 | +|------|-----------|------------|----------------| |
| 68 | +| Command execution | `src/commands/Commands.ts` | `ios/RNNCommandsHandler.mm` | `react/NavigationTurboModule.kt` | |
| 69 | +| Layout creation | `src/commands/LayoutTreeParser.ts` | `ios/RNNViewControllerFactory.mm` | `options/LayoutFactory.java` | |
| 70 | +| Options processing | `src/commands/OptionsProcessor.ts` | `ios/RNNNavigationOptions.mm` | `options/Options.java` | |
| 71 | +| Options application | — | `ios/*Presenter.mm` | `viewcontrollers/*Presenter.java` | |
| 72 | +| TopBar | `src/interfaces/Options.ts` (TopBarOptions) | `ios/TopBarPresenter.mm`, `ios/RNNUIBarButtonItem.mm` | `views/stack/topbar/` | |
| 73 | +| Bottom tabs | `src/interfaces/Options.ts` (BottomTabsOptions) | `ios/RNNBottomTabsPresenter.mm` | `viewcontrollers/bottomtabs/` | |
| 74 | +| Modals | `src/commands/Commands.ts` | `ios/RNNModalManager.mm` | `viewcontrollers/modal/ModalStack.java` | |
| 75 | +| Overlays | `src/commands/Commands.ts` | `ios/RNNOverlayManager.mm` | `viewcontrollers/overlay/OverlayManager.kt` | |
| 76 | +| Animations | `src/interfaces/Options.ts` (AnimationOptions) | `ios/ScreenAnimationController.mm` | `viewcontrollers/stack/StackAnimator.kt` | |
| 77 | +| React view rendering | — | `ios/RNNReactView.mm` | `react/ReactView.java` | |
| 78 | +| Events to JS | `src/adapters/NativeEventsReceiver.ts` | `ios/RNNEventEmitter.mm` | `react/events/EventEmitter.java` | |
| 79 | +| Component registration | `src/components/ComponentRegistry.ts` | — | — | |
| 80 | + |
| 81 | +### By directory |
| 82 | + |
| 83 | +- **`src/`** — JS public API, commands, processing pipeline. See [src/ARCHITECTURE.md](../../src/ARCHITECTURE.md) |
| 84 | +- **`ios/`** — All Obj-C/C++ native code. See [ios/ARCHITECTURE.md](../../ios/ARCHITECTURE.md) |
| 85 | +- **`ios/TurboModules/`** — New architecture entry points (`RNNTurboModule`, `RNNTurboManager`, `RNNTurboCommandsHandler`) |
| 86 | +- **`android/src/main/java/com/reactnativenavigation/`** — All Java/Kotlin native code. See [android/ARCHITECTURE.md](../../android/ARCHITECTURE.md) |
| 87 | +- **`playground/`** — Demo app for development and E2E tests |
| 88 | +- **`playground/src/screens/`** — Test screens exercising every feature |
| 89 | +- **`playground/e2e/`** — Detox E2E tests |
| 90 | + |
| 91 | +## Options Resolution Order |
| 92 | + |
| 93 | +Options are applied in ascending priority: |
| 94 | +1. Default options (from `Navigation.setDefaultOptions()`) — lowest priority |
| 95 | +2. Static options (from component class or `Navigation.registerComponent`) |
| 96 | +3. Options passed in the layout call (e.g. `push`, `setRoot`) |
| 97 | +4. `mergeOptions()` — runtime override, highest priority |
| 98 | + |
| 99 | +## JS Processing Pipeline (exact order) |
| 100 | + |
| 101 | +``` |
| 102 | +API layout → OptionsCrawler.crawl() → LayoutProcessor.process() |
| 103 | + → LayoutTreeParser.parse() → LayoutTreeCrawler.crawl() |
| 104 | + → OptionsProcessor (colors, assets, custom) → NativeCommandsSender |
| 105 | +``` |
| 106 | + |
| 107 | +## iOS Patterns |
| 108 | + |
| 109 | +- All controllers conform to `RNNLayoutProtocol` |
| 110 | +- `RNNBasePresenter` subclasses apply options — `applyOptionsOnInit:`, `applyOptions:`, `mergeOptions:resolvedOptions:` |
| 111 | +- Commands run on main thread (`RCTExecuteOnMainQueue`) |
| 112 | +- React views: `RNNReactView` wraps `RCTSurfaceHostingView` (new arch) |
| 113 | +- Overlays use separate `UIWindow` instances (`RNNOverlayWindow`) |
| 114 | +- `RNNReactComponentRegistry` caches React component instances |
| 115 | + |
| 116 | +## Android Patterns |
| 117 | + |
| 118 | +- View-based, NOT Fragment-based |
| 119 | +- All commands dispatched via `UiThread.post()` |
| 120 | +- `ViewController<T extends ViewGroup>` is the base — `createView()` is abstract |
| 121 | +- `ParentController` extends `ChildController` extends `ViewController` |
| 122 | +- Bottom tabs use `AHBottomNavigation` library |
| 123 | +- Three root layouts in `NavigationActivity`: rootLayout, modalsLayout, overlaysLayout |
| 124 | +- Tab attachment modes: `Together`, `OnSwitchToTab`, `AfterInitialTab` |
| 125 | + |
| 126 | +## Development Workflow |
| 127 | + |
| 128 | +### Playground app |
| 129 | +- `yarn start` — Metro bundler |
| 130 | +- `yarn xcode` — Open iOS project |
| 131 | +- `yarn studio` — Open Android project |
| 132 | +- `yarn pod-install` — Install iOS pods |
| 133 | + |
| 134 | +### Testing |
| 135 | +- `yarn test-js` — Jest unit tests |
| 136 | +- `yarn test-unit-ios` — iOS native unit tests (XCTest) |
| 137 | +- `yarn test-unit-android` — Android native unit tests (JUnit + Robolectric) |
| 138 | +- `yarn test-e2e-ios-ci` / `yarn test-e2e-android-ci` — Detox E2E tests |
| 139 | + |
| 140 | +### Building |
| 141 | +- `yarn prepare` — Builds `src/` → `lib/` (ESM + types) |
| 142 | +- Codegen config: `rnnavigation` in `package.json` |
| 143 | + |
| 144 | +## Common Gotchas |
| 145 | + |
| 146 | +- iOS uses UIKit subclasses (UINavigationController, UITabBarController); Android uses custom View hierarchy |
| 147 | +- `splitView` is iOS-only |
| 148 | +- Side menu: iOS uses MMDrawerController (3rd party); Android uses DrawerLayout (native) |
| 149 | +- Options that exist in JS types may not be implemented on both platforms — check the presenter |
| 150 | +- `passProps` are stored in JS `Store`, not sent to native (cleared before bridge crossing) |
| 151 | +- The `lib/` folder is generated — never edit it, edit `src/` instead |
0 commit comments