Skip to content

feat(expo): upgrade to Expo SDK 56 / React Native 0.85#2581

Merged
mikib0 merged 7 commits into
developmentfrom
feat/upgrade-expo-sdk-56
Jun 14, 2026
Merged

feat(expo): upgrade to Expo SDK 56 / React Native 0.85#2581
mikib0 merged 7 commits into
developmentfrom
feat/upgrade-expo-sdk-56

Conversation

@mikib0

@mikib0 mikib0 commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Expo SDK 55 → 56 (`expo@56.0.9`) and React Native 0.83 → 0.85.3
  • All `expo-*` sub-packages updated to their SDK 56 versions via `npx expo install --fix`
  • Added `expo-splash-screen@56.0.10` (splash screen config was split into its own package in SDK 56)
  • `@packrat-ai/nativewindui` 2.0.6 → 2.2.0 — resolves the SDK 55 duplicate native package warnings from `expo-doctor`

Breaking changes addressed

`@react-navigation/*` → `expo-router` entry points (SDK 56 requirement)

Ran the official codemod (`expo-codemod sdk-56-expo-router-react-navigation-replace`) across all source files. 6 files updated:

  • `app/_layout.tsx`, `app/_layout.web.tsx`, `theme/index.ts` — `@react-navigation/native` → `expo-router/react-navigation`
  • `app/(app)/demo/index.tsx`, `app/auth/one-time-password.tsx` — `@react-navigation/elements` → `expo-router/react-navigation`
  • `app/(app)/(tabs)/(home)/index.tsx` — `@react-navigation/native` → `expo-router/react-navigation`

Removed direct `@react-navigation/{native,elements,bottom-tabs,drawer}` deps (now transitive via `expo-router`).

`expo-navigation-bar` API removed imperative setters

`setButtonStyleAsync`, `setPositionAsync`, `setBackgroundColorAsync` are gone. Updated `useColorScheme.tsx` to use the new synchronous `NavigationBar.setStyle()`.

`ExpoConfig.splash` removed from top-level type

Migrated `splash: { image }` from the deprecated top-level `ExpoConfig` field to the `expo-splash-screen` plugin config.

Reanimated 4 `AnimatedStyleHandle` type change

Updated `checkboxContainerStyle` prop type in `conversations.tsx` from `ViewStyle` to `AnimatedStyle`.

Housekeeping

  • Removed `@babel/core` from devDeps (implicit package, managed by Expo)
  • Removed `unstable_enablePackageExports` from metro config (default since SDK 53)
  • Added `expo-status-bar` and `expo-splash-screen` to `app.config.ts` plugins
  • Updated `expo-sqlite` monorepo override from `~55` → `~56`
  • Excluded `typescript` from expo version validation (`typescript@6` upgrade is a separate effort — TS 5.9 still used across all other packages)

Test plan

  • `bun check-types` — passes with 0 errors
  • `bun lint` — passes with 0 errors (2 pre-existing warnings in `apps/web`)
  • `npx expo-doctor` — all checks pass (nativewindui is now on SDK 56 via 2.2.0)
  • iOS dev build: run `bun ios` and verify splash screen, navigation bar, and all navigated screens load correctly
  • Android dev build: verify navigation bar style switches with color scheme

Summary by CodeRabbit

  • Chores

    • Upgraded Expo SDK from v55 to v56 and React Native to v0.85.3
    • Updated splash screen configuration via Expo plugin system
    • Updated Metro bundler to handle WebAssembly assets and exclude Android build artifacts
  • Bug Fixes

    • Improved Android navigation bar styling performance by removing async behavior

- expo 55 → 56.0.9, react-native 0.83 → 0.85.3
- all expo-* packages updated to SDK 56 equivalents
- migrate @react-navigation/* imports to expo-router entry points (SDK 56 breaking change)
- remove @react-navigation/{native,elements,bottom-tabs,drawer} direct dependencies
- fix expo-navigation-bar API: setButtonStyleAsync/setPositionAsync/setBackgroundColorAsync removed, replaced with synchronous setStyle
- migrate splash config from deprecated top-level ExpoConfig.splash to expo-splash-screen plugin
- add expo-status-bar and expo-splash-screen to plugins list
- fix AnimatedStyleHandle<ViewStyle> type error in conversations.tsx (Reanimated 4)
- remove unstable_enablePackageExports from metro config (default since SDK 53)
- remove @babel/core from devDependencies (implicit package managed by Expo)
- update expo-sqlite override in root package.json: ~55 → ~56
- exclude typescript from expo version check (TS 6 upgrade is a separate effort)
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@mikib0, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 13 minutes and 56 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0d666868-e28e-4b1d-add0-7ff947aea9a1

📥 Commits

Reviewing files that changed from the base of the PR and between 1edb0c1 and 575147f.

📒 Files selected for processing (2)
  • apps/expo/lib/api/getBaseUrl.ts
  • apps/expo/playwright/tests/core.spec.ts

Walkthrough

Upgrades Expo SDK from ~55.x to ~56.x across all package manifests, migrates React Navigation imports (ThemeProvider, useIsFocused, useHeaderHeight, theme objects) from @react-navigation/native/elements to expo-router/react-navigation, rewrites Android navigation bar styling to use synchronous NavigationBar.setStyle(), migrates splash screen to plugin config, and updates Metro resolver settings.

Changes

Expo SDK 56 Upgrade

Layer / File(s) Summary
Dependency version bumps
apps/expo/package.json, package.json, packages/ui/package.json
Expo SDK bumped from ~55.x to ~56.x, expo-router to ~56.2.9, react-native to 0.85.3, react-native-reanimated to 4.3.1, @packrat-ai/nativewindui to 2.2.1, and related React Native ecosystem packages. Root-level overrides and catalog pins updated accordingly.
React Navigation import migration
apps/expo/theme/index.ts, apps/expo/app/_layout.tsx, apps/expo/app/_layout.web.tsx, apps/expo/app/(app)/(tabs)/(home)/index.tsx, apps/expo/app/(app)/demo/index.tsx, apps/expo/app/auth/one-time-password.tsx
ThemeProvider, DarkTheme, DefaultTheme, useIsFocused, and useHeaderHeight are now imported from expo-router/react-navigation instead of @react-navigation/native or @react-navigation/elements.
Android nav bar refactor, splash config, and Metro resolver
apps/expo/lib/hooks/useColorScheme.tsx, apps/expo/app.config.ts, apps/expo/metro.config.js
setNavigationBar rewritten from async expo-navigation-bar multi-call to synchronous NavigationBar.setStyle() with try/catch; await removed at call site. Splash screen moved from top-level config to expo-splash-screen plugin. Metro resolver drops unstable_enablePackageExports, adds wasm asset extension and Android .cxx blocklist.
AnimatedStyle prop type fix
apps/expo/app/(app)/messages/conversations.tsx
checkboxContainerStyle prop type on MessageRow changed from ViewStyle to AnimatedStyle<ViewStyle>.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • andrew-bierman
  • Isthisanmol
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: upgrading Expo SDK from 55 to 56 and React Native from 0.83 to 0.85, which aligns with the package.json updates and breaking change migrations throughout the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/upgrade-expo-sdk-56

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file api ci/cd mobile database labels Jun 10, 2026
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for packages/overpass (./packages/overpass)

Status Category Percentage Covered / Total
🔵 Lines 100% (🎯 80%) 155 / 155
🔵 Statements 100% (🎯 80%) 155 / 155
🔵 Functions 100% (🎯 80%) 13 / 13
🔵 Branches 95.65% (🎯 70%) 44 / 46
File CoverageNo changed files found.
Generated in workflow #272 for commit 575147f by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for apps/expo (./apps/expo)

Status Category Percentage Covered / Total
🔵 Lines 97.52% (🎯 95%) 590 / 605
🔵 Statements 97.52% (🎯 95%) 590 / 605
🔵 Functions 100% (🎯 97%) 51 / 51
🔵 Branches 95.3% (🎯 92%) 203 / 213
File CoverageNo changed files found.
Generated in workflow #272 for commit 575147f by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for packages/analytics (./packages/analytics)

Status Category Percentage Covered / Total
🔵 Lines 93.68% (🎯 80%) 697 / 744
🔵 Statements 93.68% (🎯 80%) 697 / 744
🔵 Functions 97.87% (🎯 85%) 46 / 47
🔵 Branches 85.8% (🎯 80%) 133 / 155
File CoverageNo changed files found.
Generated in workflow #272 for commit 575147f by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for packages/units (./packages/units)

Status Category Percentage Covered / Total
🔵 Lines 100% (🎯 100%) 35 / 35
🔵 Statements 100% (🎯 100%) 35 / 35
🔵 Functions 100% (🎯 100%) 6 / 6
🔵 Branches 100% (🎯 100%) 11 / 11
File CoverageNo changed files found.
Generated in workflow #272 for commit 575147f by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for packages/mcp (./packages/mcp)

Status Category Percentage Covered / Total
🔵 Lines 98.87% (🎯 95%) 176 / 178
🔵 Statements 98.87% (🎯 95%) 176 / 178
🔵 Functions 100% (🎯 95%) 13 / 13
🔵 Branches 98.38% (🎯 90%) 61 / 62
File CoverageNo changed files found.
Generated in workflow #272 for commit 575147f by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for packages/api (./packages/api)

Status Category Percentage Covered / Total
🔵 Lines 98.95% (🎯 95%) 1322 / 1336
🔵 Statements 98.95% (🎯 95%) 1322 / 1336
🔵 Functions 100% (🎯 97%) 74 / 74
🔵 Branches 95.62% (🎯 92%) 481 / 503
File CoverageNo changed files found.
Generated in workflow #272 for commit 575147f by the Vitest Coverage Report Action

mikib0 added 2 commits June 13, 2026 15:46
Bumps the nativewindui package across all three consumers
(root override, packages/ui, apps/expo) from 2.0.6 → 2.2.0.
React Native 0.85.3 bundles react-native-renderer@19.2.3. The previous
override of react@19.2.6 caused an "Incompatible React versions" crash
on startup.
@mikib0 mikib0 changed the base branch from main to development June 14, 2026 06:59
mikib0 added 2 commits June 14, 2026 09:01
Fixes Android crash — "Couldn't find a route object" — caused by LargeTitleHeader
importing useRoute from @react-navigation/native, which reads from a different
NavigationRouteContext than the one expo-router SDK 56 populates. The fix is
shipped in 2.2.1, so the 2.2.0 patch is no longer needed and is removed.
@github-actions github-actions Bot removed documentation Improvements or additions to documentation api ci/cd database labels Jun 14, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/expo/app.config.ts`:
- Around line 80-82: The `expo-navigation-bar` plugin is missing from the
plugins array in the app config. Add a new entry to the plugins array (alongside
the other plugins like `@sentry/react-native`, `expo-status-bar`, and
`expo-splash-screen`) that includes the `expo-navigation-bar` plugin configured
with `enforceContrast: false` as an object parameter. This configuration is
required for the `NavigationBar.setStyle()` calls in `useColorScheme.tsx` to
work properly; without it, the OS will override manual style changes and the
Android theme-sync will not function.

In `@apps/expo/lib/hooks/useColorScheme.tsx`:
- Around line 13-17: The catch block for the setNavigationBar call in
useColorScheme.tsx only logs errors to console and does not report them to
Sentry for production telemetry tracking. Import captureException from
`@sentry/react-native` at the top of the file, then in the catch block, call
Sentry.captureException(error) before or after the console.error call to ensure
the error is captured in production telemetry while preserving the original
error object and logging behavior. This aligns with the coding guidelines
requiring Sentry capture in all catch blocks for files under apps/expo.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0638f44d-d133-486a-92f2-90c123e11fb2

📥 Commits

Reviewing files that changed from the base of the PR and between a2f74d3 and 1edb0c1.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock, !bun.lock
📒 Files selected for processing (13)
  • apps/expo/app.config.ts
  • apps/expo/app/(app)/(tabs)/(home)/index.tsx
  • apps/expo/app/(app)/demo/index.tsx
  • apps/expo/app/(app)/messages/conversations.tsx
  • apps/expo/app/_layout.tsx
  • apps/expo/app/_layout.web.tsx
  • apps/expo/app/auth/one-time-password.tsx
  • apps/expo/lib/hooks/useColorScheme.tsx
  • apps/expo/metro.config.js
  • apps/expo/package.json
  • apps/expo/theme/index.ts
  • package.json
  • packages/ui/package.json
💤 Files with no reviewable changes (1)
  • apps/expo/metro.config.js

Comment thread apps/expo/app.config.ts
Comment on lines 80 to +82
'@sentry/react-native',
'expo-status-bar',
['expo-splash-screen', { image: './assets/splash.png' }],

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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Find and inspect useColorScheme.tsx to confirm NavigationBar.setStyle usage
find apps/expo -name "useColorScheme.tsx" -type f

Repository: PackRat-AI/PackRat

Length of output: 101


🏁 Script executed:

# Check the full app.config.ts to see complete plugin list and verify expo-navigation-bar absence
cat -n apps/expo/app.config.ts | head -100

Repository: PackRat-AI/PackRat

Length of output: 3613


🏁 Script executed:

# Search for NavigationBar references in the codebase
rg "NavigationBar" apps/expo/ -A 3 -B 2

Repository: PackRat-AI/PackRat

Length of output: 1930


🌐 Web query:

expo-navigation-bar enforceContrast plugin configuration setStyle

💡 Result:

In the expo-navigation-bar plugin, the enforceContrast configuration option determines whether the operating system maintains a translucent navigation bar to ensure contrast between navigation buttons and your app content [1][2][3]. Plugin Configuration: You can configure this in your app.json (or app.config.js/ts) file within the plugins array. Setting enforceContrast to true (the default) enables this behavior [1][2][3]: { "expo": { "plugins": [ [ "expo-navigation-bar", { "enforceContrast": true, "barStyle": "light", "visibility": "visible" } ] ] } } Important Note on setStyle: The NavigationBar.setStyle(style) and NavigationBar.setButtonStyleAsync(style) functions are designed to control the color of navigation bar buttons (e.g., light or dark) [1][2][3]. However, these functions will only have an effect if the following conditions are met: 1. The enforceContrast option is set to false [1][2][3]. 2. The device is using the traditional three-button navigation bar (this does not work with gesture navigation) [1][2][4]. If enforceContrast remains true (the default), the operating system overrides manual style settings to ensure visibility, rendering setStyle calls ineffective [1][2]. Additionally, please note that there is a known bug in some Android emulator versions (notably Android 15) that may prevent these functions from working even when conditions are met [1][5][3].

Citations:


Add the expo-navigation-bar plugin with enforceContrast: false—otherwise NavigationBar.setStyle() calls will be silently ignored.

The new setStyle() calls in useColorScheme.tsx depend on the expo-navigation-bar plugin configured with enforceContrast: false. Without this config, the OS overrides manual style changes, making the Android theme-sync a no-op. (Note: this also only works on traditional three-button navigation, not gesture navigation.)

Suggested fix
         '`@react-native-community/datetimepicker`',
         '`@sentry/react-native`',
+        ['expo-navigation-bar', { enforceContrast: false }],
         'expo-status-bar',
         ['expo-splash-screen', { image: './assets/splash.png' }],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'@sentry/react-native',
'expo-status-bar',
['expo-splash-screen', { image: './assets/splash.png' }],
'`@sentry/react-native`',
['expo-navigation-bar', { enforceContrast: false }],
'expo-status-bar',
['expo-splash-screen', { image: './assets/splash.png' }],
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/expo/app.config.ts` around lines 80 - 82, The `expo-navigation-bar`
plugin is missing from the plugins array in the app config. Add a new entry to
the plugins array (alongside the other plugins like `@sentry/react-native`,
`expo-status-bar`, and `expo-splash-screen`) that includes the
`expo-navigation-bar` plugin configured with `enforceContrast: false` as an
object parameter. This configuration is required for the
`NavigationBar.setStyle()` calls in `useColorScheme.tsx` to work properly;
without it, the OS will override manual style changes and the Android theme-sync
will not function.

Comment on lines 13 to 17
try {
await setNavigationBar(colorScheme);
setNavigationBar(colorScheme);
} catch (error) {
console.error('useColorScheme.tsx", "setColorScheme', error);
}

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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's check if the file exists and examine its structure
fd -t f "useColorScheme.tsx" apps/expo/

Repository: PackRat-AI/PackRat

Length of output: 101


🏁 Script executed:

# Once we have the file path, let's examine the actual content
cat -n apps/expo/lib/hooks/useColorScheme.tsx

Repository: PackRat-AI/PackRat

Length of output: 1986


🏁 Script executed:

# Let's also verify the Sentry import guideline applies by checking current imports in the file
head -20 apps/expo/lib/hooks/useColorScheme.tsx

Repository: PackRat-AI/PackRat

Length of output: 768


Capture these native failures with Sentry instead of only logging them.

Both catch blocks only call console.error, so Android navigation-bar sync failures during theme toggles disappear from production telemetry. These errors should be reported with @sentry/react-native while preserving the original error object.

Suggested fix
+import * as Sentry from '`@sentry/react-native`';
 import { COLORS } from 'expo-app/theme/colors';
 import * as NavigationBar from 'expo-navigation-bar';
 import { useColorScheme as useNativewindColorScheme } from 'nativewind';
 import * as React from 'react';
 import { Platform } from 'react-native';
@@
     try {
       setNavigationBar(colorScheme);
     } catch (error) {
+      Sentry.captureException(error);
       console.error('useColorScheme.tsx", "setColorScheme', error);
     }
@@
   try {
     NavigationBar.setStyle(colorScheme === 'dark' ? 'light' : 'dark');
   } catch (error) {
+    Sentry.captureException(error);
     console.error('useColorScheme.tsx', 'setNavigationBar', error);
   }
 }

Coding guidelines require Sentry capture in all catch blocks for files under apps/expo/**/*.{ts,tsx}.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/expo/lib/hooks/useColorScheme.tsx` around lines 13 - 17, The catch block
for the setNavigationBar call in useColorScheme.tsx only logs errors to console
and does not report them to Sentry for production telemetry tracking. Import
captureException from `@sentry/react-native` at the top of the file, then in the
catch block, call Sentry.captureException(error) before or after the
console.error call to ensure the error is captured in production telemetry while
preserving the original error object and logging behavior. This aligns with the
coding guidelines requiring Sentry capture in all catch blocks for files under
apps/expo.

Source: Coding guidelines

mikib0 added 2 commits June 14, 2026 09:12
Physical devices can reach localhost directly; only the Android emulator
needs the 10.0.2.2 alias. Guard the rewrite with !Device.isDevice.
getByText(/Add \d+ item/i) matched two elements; adding .first() satisfies Playwright's strict mode.
@mikib0 mikib0 merged commit cd4e217 into development Jun 14, 2026
22 of 23 checks passed
@mikib0 mikib0 deleted the feat/upgrade-expo-sdk-56 branch June 14, 2026 08:54
@coderabbitai coderabbitai Bot mentioned this pull request Jun 15, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file mobile

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant