Skip to content

feat(mobile): upgrade RN deps for new-arch readiness (old arch still on)#14505

Open
dylanjeffers wants to merge 4 commits into
mainfrom
feat/rn-package-upgrades
Open

feat(mobile): upgrade RN deps for new-arch readiness (old arch still on)#14505
dylanjeffers wants to merge 4 commits into
mainfrom
feat/rn-package-upgrades

Conversation

@dylanjeffers

Copy link
Copy Markdown
Contributor

Summary

Upgrades the React Native dependency surface for New-Architecture readiness while keeping the old architecture on. Lands the app on RN 0.81.6 — the last version that supports the legacy architecture — and replaces the abandoned/incompatible native gradient + filesystem + crypto libraries with new-arch-ready equivalents. Each step was validated with a clean npm run ios:prod.

Scope note / re-strategy. The original ask was "swap deps + RN 0.82 + Reanimated 4, new arch off." That end state is internally impossible: RN 0.82 makes New Architecture mandatory (newArchEnabled=false is ignored), and Reanimated 4 is new-arch-only (crashes on first start on old arch). So this PR is scoped to the genuine old-arch ceilingRN 0.81 + Reanimated 3 — which is also the documented launchpad for the later new-arch flip. New Architecture stays off throughout (Android newArchEnabled=false, iOS RCTNewArchEnabled=false).

What's in here (4 commits)

  1. react-native-fs@dr.pogodin/react-native-fs@2.32.1 and react-native-fast-crypto@noble/hashes scrypt.

    • fs fork pinned to 2.32.1 because 2.33+ uses a CodegenTypes.EventEmitter spec the current codegen parser rejects; 2.32.1 uses method-callback specs that build cleanly. Default import → namespace import (the fork has no default export).
    • scrypt swap is wallet-key-critical — verified byte-for-byte output parity against RFC 7914 for the exact params (N=32768, r=8, p=1, dkLen=32) and the existing UTF-8 salt encoding, so derived keys are unchanged. Uses scryptAsync to stay off the JS critical path the way the native module did.
  2. Native gradient libs → react-native-svg (already linked & new-arch ready).

    • New harmony-native LinearGradient built on react-native-svg (renders an absolutely-positioned SVG behind children via objectBoundingBox, so it works as both a fill and a container). All 22 call sites repointed; useAngle/angle props converted to start/end via a new getGradientStartEnd helper.
    • react-native-radial-gradient → rewritten on svg's <RadialGradient>; custom SRSRadialGradient pod removed.
    • Why not expo-linear-gradient? This app isn't wired for Expo native autolinking (use_expo_modules! absent, ExpoModulesCore not linked, expo@51 is an unused ghost dep mismatched against RN 0.79), so expo-linear-gradient could not link/render here. svg avoids dragging in Expo's native subsystem.
  3. RN 0.79.5 → 0.80.3 + React 19.0.0 → 19.1.8 monorepo-wide (RN 0.80 requires react ^19.1.0; bumped via the root overrides + every package declaration). Converted the 5 deprecated react-native/types deep imports.

  4. RN 0.80.3 → 0.81.6. React stays 19.1.8 (satisfies ^19.1.4). Fixed two RN-0.81 type tightenings (TextInput blur event lost text; narrowed an ExternalLink prop spread).

Validation

  • npm run ios:prodgreen at every checkpoint (Group 1, Group 2, RN 0.80, RN 0.81, final).
  • tsc --noEmit clean (0 errors) and full eslint clean at the final state.
  • New arch verified off: Android newArchEnabled=false, iOS RCTNewArchEnabled=false.

⚠️ Reviewer caveats

  • React 19.0 → 19.1 is monorepo-wide (via the global overrides), so it changes the web app's React version too. Validated on iOS only — web should be smoke-tested separately. (19.1 is a low-risk minor.)
  • iOS-validated only. Android gradle config that RN 0.81 expects (compileSdk/targetSdk 36, edge-to-edge) is not updated here — needs a separate Android-validated pass.

Deferred to a follow-up (Phase B — the actual new-arch flip)

RN 0.82+ (new arch becomes mandatory), Reanimated 4 + react-native-worklets, gesture-handler 3 / flash-list 2, and the flagged hard libs: react-native-track-player v5 (commercial license), react-native-collapsible-tab-view replacement, react-native-google-cast Fabric decision, and the wix react-native-notifications → notifee + Firebase rewrite (deferred so it can get real push testing).

🤖 Generated with Claude Code

dylanjeffers and others added 4 commits June 23, 2026 15:24
…crypto

Swap two unmaintained native deps for new-arch-ready replacements (old
architecture stays on; no behavior change):

- react-native-fs (abandoned 2022) -> @dr.pogodin/react-native-fs@2.32.1.
  Pinned to 2.32.1 because 2.33+ uses a CodegenTypes.EventEmitter spec that
  RN 0.79's codegen parser rejects; 2.32.1 uses method-callback specs that
  build on the current RN. API is identical; default import becomes a
  namespace import since the fork has no default export.
- react-native-fast-crypto (old-bridge only) -> @noble/hashes scrypt (pure
  JS). Verified byte-for-byte output parity against RFC 7914 for the exact
  params (N=32768,r=8,p=1,dkLen=32) and the existing UTF-8 salt encoding, so
  derived wallet keys are unchanged. Uses scryptAsync to stay off the JS
  critical path the way the native module did.

Validated with a clean `npm run ios:prod` build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both native gradient packages are unmaintained with no new-architecture
support, so move them onto react-native-svg (already linked and new-arch
ready). Old architecture stays on; no Expo native modules are introduced
(this app isn't wired for Expo autolinking, so expo-linear-gradient could
not link here).

- react-native-linear-gradient -> new harmony-native `LinearGradient` built
  on react-native-svg. Renders the gradient as an absolutely-positioned SVG
  behind any children via `objectBoundingBox` units, so it works as both a
  fill and a container with no layout measurement. All 22 call sites
  repointed; `useAngle`/`angle` props converted to `start`/`end` via a new
  `getGradientStartEnd` helper that reproduces the bearing-angle direction.
- react-native-radial-gradient -> rewrite harmony-native `RadialGradient` on
  react-native-svg's `<RadialGradient>` (userSpaceOnUse to keep it circular,
  matching the old percentage center/radius API). Removed the custom
  SRSRadialGradient pod from the Podfile.

Typecheck and lint clean; validated with a clean `npm run ios:prod`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First rung of the RN ladder. New Architecture stays off — pod install
baked RCTNewArchEnabled=false into the iOS Info.plists.

- react-native 0.79.5 -> 0.80.3, @react-native/* 0.79.5 -> 0.80.3,
  @react-native-community/cli 18 -> 19.1.2.
- React 19.0.0 -> 19.1.8 monorepo-wide (RN 0.80 requires react ^19.1.0).
  Bumped via the root `overrides` plus every package's declaration so web
  and mobile stay aligned; @types/react -> 19.1.17, @types/react-dom ->
  19.1.11. Reanimated intentionally stays on 3.x (4.x is new-arch only).
- Converted the 5 deprecated `react-native/types` deep imports to root
  `react-native` imports (0.80 deprecation).
- Clean pod reinstall to re-resolve the RN 0.80 pod set.

Typecheck + lint clean; validated with a clean `npm run ios:prod`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Final rung of the RN ladder — lands on 0.81, the last version that supports
the legacy architecture. New Architecture stays off (Android
newArchEnabled=false, iOS RCTNewArchEnabled=false). Reanimated stays on 3.x.

- react-native 0.80.3 -> 0.81.6, @react-native/* -> 0.81.6,
  @react-native-community/cli 19.1.2 -> 20.1.3. React stays 19.1.8
  (satisfies 0.81's react ^19.1.4).
- Fixed two type regressions from RN 0.81's stricter prop types:
  - HarmonyTextField: the TextInput blur event type dropped `text`; cast to
    read it (still present at runtime) so transformValueOnBlur is unchanged.
  - ExternalLink: narrow the forwarded TouchableWithoutFeedback prop spread
    to satisfy TextPressable's prop type.
- Clean pod reinstall for the RN 0.81 pod set.

NOTE: validated on iOS only via `npm run ios:prod`. Android gradle config
(API 36 / edge-to-edge that RN 0.81 expects) is NOT updated here and needs a
separate Android-validated pass.

Typecheck + lint clean; validated with a clean `npm run ios:prod`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 115e2db

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@socket-security

Copy link
Copy Markdown

Dependency limit exceeded — report not shown.

This pull request scan exceeded the 10,000-dependency limit applied to this scan, so the results are incomplete and may be inaccurate. To avoid reporting false positives, Socket has not posted a report.

Upgrade your plan to raise the dependency limit and get complete reports, or view the partial scan in the dashboard.

Socket is always free for open source. If this is a non-commercial open source project, contact us to request a free Team account.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant