Skip to content

chore: migrate React Navigation to v6#26691

Merged
andrepimenta merged 269 commits into
mainfrom
feat/react-navigation-v6-migration
Mar 31, 2026
Merged

chore: migrate React Navigation to v6#26691
andrepimenta merged 269 commits into
mainfrom
feat/react-navigation-v6-migration

Conversation

@asalsys

@asalsys asalsys commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

Description

This PR migrates React Navigation from v5 to v6. This is a significant infrastructure update that modernizes the navigation layer of the application to align with the latest React Navigation best practices and removes deprecated APIs.

Why this change?

  • React Navigation v5 is no longer actively maintained
  • v6 provides improved TypeScript support, better performance, and simplified APIs
  • Removes the deprecated @react-navigation/compat package

What changed?

v5 API v6 API
mode="modal" prop on Navigator screenOptions={{ presentation: 'modal' }}
headerMode="screen" prop Removed (default behavior in v6)
headerMode="none" prop screenOptions={{ headerShown: false }}
dangerouslyGetParent() getParent()
dangerouslyGetState() getState()
NavigationContainerRef NavigationContainerRef<ParamListBase>

Dependencies updated:

  • @react-navigation/bottom-tabs: ^5.11.11^6.6.1
  • @react-navigation/native: ^5.9.4^6.1.18
  • @react-navigation/stack: ^5.14.5^6.4.1
  • Removed @react-navigation/compat (deprecated v5 compatibility package)

Changelog

CHANGELOG entry: null

Related issues

fixes: React Navigation v6 Migration

Manual testing steps

Feature: React Navigation v6 Migration

  Scenario: user navigates between main tabs
    Given the app is launched and user is logged in
    When user taps on each tab (Wallet, Browser, Activity, etc.)
    Then each tab screen renders correctly with proper animations

  Scenario: user opens a modal screen
    Given the user is on the Wallet screen
    When user triggers a modal (e.g., WalletActions, NetworkSelector)
    Then the modal presents with correct slide-up animation
    And the modal dismisses correctly when closed

  Scenario: user navigates with back button
    Given the user has navigated deep into a stack (e.g., Settings > Security)
    When user presses the back button or swipes back
    Then navigation returns to the previous screen correctly

  Scenario: user opens bottom sheets
    Given the user is on any screen with bottom sheet functionality
    When user triggers a bottom sheet (e.g., Account Connect, Token Sort)
    Then the bottom sheet presents correctly over the current screen
    And background content remains visible behind transparent areas

Screenshots/Recordings

Before

N/A - No visual changes expected

After

No visual changes expected. To ensure that the ui has not changed #27385 was created to view the comparison of ui through the flow via visual regression

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

High Risk
Touches core navigation structure and presentation settings across many stacks/modals, so regressions could break routing, back behavior, or modal/sheet presentation. Changes also alter theming/background handling, which can cause subtle UI layering issues.

Overview
Updates app navigation to React Navigation v6 patterns by removing deprecated navigator props like mode and moving modal behavior to screenOptions.presentation (and related per-screen options), while centralizing clearStackNavigatorOptions and adjusting many flows (App, MainNavigator, RootModalFlow, rewards/browser/etc.) to set appropriate cardStyle backgrounds.

Refactors navigation typings (e.g., TabBarProps/descriptors and NavigationContainerRef<ParamListBase>), hardens TabBar against missing descriptors, and expands unit tests/snapshots to cover tab visibility/callbacks/on-leave behavior plus broad route/screen registration validation. NavigationContainer theme background is set to transparent to support transparent modals, shifting responsibility for background color to screens.

Written by Cursor Bugbot for commit b6a3bcb. This will update automatically on new commits. Configure here.

@metamaskbot metamaskbot added the team-mobile-platform Mobile Platform team label Feb 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@asalsys asalsys self-assigned this Feb 27, 2026
@socket-security

socket-security Bot commented Feb 27, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​react-navigation/​bottom-tabs@​5.11.11 ⏵ 6.6.19910075100 +1100
Updatednpm/​@​react-navigation/​native@​5.9.4 ⏵ 6.1.189910075 +1100 +1100
Updatednpm/​@​react-navigation/​stack@​5.14.9 ⏵ 6.4.19810077100100

View full report

@codecov-commenter

codecov-commenter commented Mar 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 64.44444% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.59%. Comparing base (9564fd6) to head (05362b0).
⚠️ Report is 14 commits behind head on main.

Files with missing lines Patch % Lines
app/components/Nav/Main/MainNavigator.js 7.69% 12 Missing ⚠️
app/components/Nav/App/App.tsx 71.42% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #26691      +/-   ##
==========================================
+ Coverage   82.52%   82.59%   +0.06%     
==========================================
  Files        4800     4829      +29     
  Lines      123748   123971     +223     
  Branches    27576    27614      +38     
==========================================
+ Hits       102122   102391     +269     
+ Misses      14567    14527      -40     
+ Partials     7059     7053       -6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

asalsys added 14 commits March 10, 2026 11:49
Resolved modify/delete conflict by accepting main's deletion of
app/components/UI/Bridge/Views/BridgeView/__snapshots__/BridgeView.test.tsx.snap

Made-with: Cursor
Add mock for @metamask/geolocation-controller module which was causing
multiple test suites across all shards to fail with "Cannot find module"
error. This mock provides the GeolocationApiService class and Env enum
required by geolocation-api-service-init.ts.

Made-with: Cursor
Update snapshots for React Navigation v6 migration changes in shard 1.
The navigation component structure has changed, requiring snapshot updates.

Made-with: Cursor
Update snapshots for React Navigation v6 migration changes in shard 2.
Also add performance tests to testPathIgnorePatterns to prevent Playwright
tests from being run by Jest.

Made-with: Cursor
Update snapshots for React Navigation v6 migration changes in shard 3.
Also enhance GeolocationController mock with getDefaultGeolocationControllerState,
GeolocationController class, and UNKNOWN_LOCATION constant.

Made-with: Cursor
Update snapshots for React Navigation v6 migration changes in shard 4.

Made-with: Cursor
Update snapshots and fix React Navigation v6 API changes:
- UnsupportedRegionModal.test.tsx: Replace dangerouslyGetParent with getParent
- NavbarTitle/index.test.js: Add useNavigation mock for React Navigation v6

Made-with: Cursor
Update snapshots and fix React Navigation v6 API changes:
- Quotes.test.tsx: Replace dangerouslyGetParent with getParent

Made-with: Cursor
- Exclude view tests (*.view.test.*) from regular unit tests in jest.config.js
  (they run with jest.config.view.js separately)
- ConfigurationModal.test.tsx: Add nested getParent mock for React Navigation v6

Made-with: Cursor
Update snapshots for React Navigation v6 migration changes in shard 9.

Made-with: Cursor
Update snapshots and fix GeolocationController mock:
- Add complete state structure (status, lastFetchedAt, error)
- Update initial-background-state.json with correct isEligible value for PerpsController

Made-with: Cursor
matallui
matallui previously approved these changes Mar 30, 2026
asalsys added 4 commits March 30, 2026 11:46
…-v6-migration

Made-with: Cursor

# Conflicts:
#	app/components/UI/Rewards/Views/OndoCampaignDetailsView.tsx
…om/MetaMask/metamask-mobile into feat/react-navigation-v6-migration

Made-with: Cursor

# Conflicts:
#	app/components/UI/Rewards/Views/OndoCampaignDetailsView.tsx
sophieqgu
sophieqgu previously approved these changes Mar 30, 2026
@@ -1,978 +0,0 @@
import { act, fireEvent } from '@testing-library/react-native';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@asalsys How come this test suite was deleted?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding back

@@ -28,25 +28,28 @@ const clearStackNavigatorOptions = {
animationEnabled: false,
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type ScreenComponent = React.ComponentType<any>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@asalsys Is there a cleaner way to go about this instead of asserting in every routes file? If we absolutely want assertions in all routes files could we create a shared type instead of redefining it?

@asalsys asalsys Mar 30, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the I have a follow up PR for stake: #28108. Since this PR is getting too big I didn't want to have it do addition typing

mcmire
mcmire previously approved these changes Mar 30, 2026

@mcmire mcmire left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Core Platform team changes look good, let me know when you need another approval.

@amitabh94

amitabh94 commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Are we not doing any before and after videos for such a big PR ? I would definitely like to see some for the Ramps flow before approving.

asalsys added 3 commits March 30, 2026 15:35
…-v6-migration

Made-with: Cursor

# Conflicts:
#	app/components/Nav/Main/MainNavigator.js
#	app/components/Nav/Main/MainNavigator.test.tsx
#	app/components/UI/Predict/views/PredictBuyWithAnyToken/PredictBuyWithAnyToken.test.tsx
#	app/components/UI/Ramp/Aggregator/Views/Modals/Settings/__snapshots__/SettingsModal.test.tsx.snap
#	app/components/UI/Ramp/Deposit/Views/Modals/ConfigurationModal/ConfigurationModal.test.tsx
#	app/components/UI/Ramp/Deposit/Views/Modals/ConfigurationModal/__snapshots__/ConfigurationModal.test.tsx.snap
#	app/components/UI/Ramp/Deposit/Views/Modals/TokenSelectorModal/__snapshots__/TokenSelectorModal.test.tsx.snap
#	app/components/UI/Ramp/Views/Modals/ErrorDetailsModal/__snapshots__/ErrorDetailsModal.test.tsx.snap
#	app/components/UI/Ramp/Views/Modals/SettingsModal/__snapshots__/SettingsModal.test.tsx.snap
#	app/components/UI/Ramp/Views/Settings/RegionSelector/__snapshots__/RegionSelector.test.tsx.snap
#	app/components/UI/Ramp/Views/TokenSelection/__snapshots__/TokenSelection.test.tsx.snap
#	app/components/UI/Ramp/components/EligibilityFailedModal/__snapshots__/EligibilityFailedModal.test.tsx.snap
#	app/components/UI/Ramp/components/RampUnsupportedModal/__snapshots__/RampUnsupportedModal.test.tsx.snap
hmalik88
hmalik88 previously approved these changes Mar 30, 2026

@hmalik88 hmalik88 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving for accounts

@asalsys

asalsys commented Mar 30, 2026

Copy link
Copy Markdown
Contributor Author

Are we not doing any before and after videos for such a big PR ? I would definitely like to see some for the Ramps flow before approving.

@amitabh94 I created a comparison PR that would run different flows of the app and do a visual regression test:

https://github.com/MetaMask/metamask-mobile/pull/27385/changes

In the above PR you can see all the screenshots throughout the flow. The reason we did not merge the visual regression pr was because the decision on whether or not to switch to maestro was not yet made. In the PR description under after I explain how the before images are to be the same as the after. This PR was also designed to just get an understanding of how the screens would look just for this PR. It can be useful to other PRs but it was not designed to be pushed to prod.

@asalsys

asalsys commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

Are we not doing any before and after videos for such a big PR ? I would definitely like to see some for the Ramps flow before approving.

@amitabh94 I created a comparison PR that would run different flows of the app and do a visual regression test:

https://github.com/MetaMask/metamask-mobile/pull/27385/changes

In the above PR you can see all the screenshots throughout the flow. The reason we did not merge the visual regression pr was because the decision on whether or not to switch to maestro was not yet made. In the PR description under after I explain how the before images are to be the same as the after. This PR was also designed to just get an understanding of how the screens would look just for this PR. It can be useful to other PRs but it was not designed to be pushed to prod.

@amitabh94

Ramp-Upgraded-Nav.mov

amitabh94
amitabh94 previously approved these changes Mar 31, 2026
@sonarqubecloud

Copy link
Copy Markdown

@tylerc-consensys tylerc-consensys left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve for screen code changes that is under web3auth

bergarces
bergarces previously approved these changes Mar 31, 2026
…-v6-migration

Made-with: Cursor

# Conflicts:
#	app/components/Views/ProtectWalletMandatoryModal/ProtectWalletMandatoryModal.test.tsx

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 6 total unresolved issues (including 5 from previous reviews).

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

mode={'modal'}
initialRouteName={'Home'}
>
<Stack.Screen name="Home" component={HomeTabs} />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Home screen reordered changes initial render in MainNavigator

Medium Severity

The Home screen was moved from after CollectiblesDetails/DeprecatedNetworkDetails to being the first Stack.Screen child. In React Navigation v6, the first screen in a stack is treated as the initial screen when no initialRouteName matches. While initialRouteName={'Home'} is set, the screen ordering change combined with the removal of mode={'modal'} means CollectiblesDetails and DeprecatedNetworkDetails now only get presentation: 'modal' individually, but many other screens in this navigator (like Send, Webview, AddBookmarkView, OfflineModeView, NftDetails, etc.) that previously inherited modal presentation from mode={'modal'} no longer present as modals.

Fix in Cursor Fix in Web

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeConfirmations, SmokeIdentity, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeTrade, SmokeWalletPlatform, SmokeCard, SmokePerps, SmokeRamps, SmokeMultiChainAPI, SmokePredictions, FlaskBuildTests
  • Selected Performance tags: @PerformanceLaunch, @PerformanceLogin, @PerformanceAssetLoading
  • Risk Level: high
  • AI Confidence: 88%
click to see 🤖 AI reasoning details

E2E Test Selection:
This PR makes extensive changes across the entire app's navigation infrastructure and multiple feature-specific route files. The risk level is HIGH because:

  1. Core Navigation Changes (Critical Risk): TabBar.tsx, App.tsx, MainNavigator.js, and NavigationProvider.tsx are foundational navigation components. Changes here affect EVERY test that navigates between screens. The TabBar is used by virtually all E2E tests to navigate between wallet, activity, browser, trending, and settings tabs. Any regression here would break most tests.

  2. Route File Changes: Multiple route files were modified:

    • Ramp/Aggregator/routes/index.tsx → affects SmokeRamps
    • Card/routes/index.tsx → affects SmokeCard
    • Earn/routes/index.tsx → affects SmokeTrade (staking)
    • Perps/routes/index.tsx → affects SmokePerps
    • Predict/routes/index.tsx → affects SmokePredictions
    • Bridge/routes.tsx → affects SmokeTrade (bridge)
  3. Multichain Transaction Components: MultichainTransactionListItem.tsx and MultichainTransactionDetailsSheet.tsx affect activity/transaction history views used in SmokeWalletPlatform, SmokeNetworkExpansion, and SmokeConfirmations.

  4. Card Feature Changes: DaimoPayModal.tsx (new WebView-based payment modal with BackgroundBridge integration) and SpendingLimitOptionsSheet.tsx are significant Card feature changes.

  5. Ramp Changes: Checkout.tsx, SettingsModal.tsx, useHandleSuccessfulOrder.ts affect the buy/sell flow.

  6. BackupAlert.tsx: Affects wallet security flows used in SmokeAccounts.

  7. PredictFeed.tsx: Major UI component for predictions.

  8. MarketInsightsView.tsx: Market insights view.

Since the TabBar and MainNavigator are shared infrastructure used by ALL tests, and multiple route files were changed across all feature areas, running all available test tags is the appropriate conservative approach. The navigation changes alone justify running all tags since any navigation regression would affect every test suite.

Tag dependencies satisfied:

  • SmokeTrade → SmokeConfirmations ✓
  • SmokeCard → SmokeTrade + SmokeConfirmations ✓
  • SmokePerps → SmokeWalletPlatform + SmokeConfirmations ✓
  • SmokePredictions → SmokeWalletPlatform + SmokeConfirmations ✓
  • SmokeMultiChainAPI → SmokeNetworkAbstractions + SmokeNetworkExpansion ✓
  • SmokeNetworkExpansion (Solana) → SmokeConfirmations ✓
  • SmokeAccounts (multi-SRP) → SmokeWalletPlatform + SmokeIdentity ✓
  • FlaskBuildTests: App.tsx and MainNavigator.js changes affect the Snaps navigation stack (SnapsSettingsStack is registered in MainNavigator, and App.tsx contains the full navigation tree that Snaps tests rely on)

Performance Test Selection:
The navigation infrastructure changes (TabBar.tsx, App.tsx, MainNavigator.js) could impact app launch performance and initial render times. TabBar is rendered on every screen transition and its changes could affect navigation performance. App.tsx changes affect the root navigation tree initialization which impacts launch and login performance. The multichain transaction list item changes could affect asset loading performance. @PerformanceLaunch covers cold/warm start and time-to-interactive which would be affected by App.tsx and MainNavigator changes. @PerformanceLogin covers session restoration which goes through the App navigation stack. @PerformanceAssetLoading covers token list rendering which includes the activity/transaction list components that were modified.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
17 value mismatches detected (expected — fixture represents an existing user).
View details

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.73.0 Issue or pull request that will be included in release 7.73.0 risk-high Extensive testing required · High bug introduction risk size-XL team-mobile-platform Mobile Platform team

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

[NAV UPGRADE - 5] Upgrade navigation library to V6