Mobile — React Native Development

React Native Brownfield Integration in Existing Apps

Direct answer

Brownfield integration embeds React Native inside an existing native iOS or Android app: the native app keeps its shell — navigation, auth, push — and mounts React Native views for specific flows, each registered under a name via AppRegistry and receiving context like session tokens through initial properties. It is the standard path for incremental migrations and for adding cross-platform feature velocity to a large native app without a rewrite, at the cost of owning the build-integration seam.

Most React Native content assumes a greenfield app, but some of the highest-leverage work is the opposite: dropping React Native into a large, living native app so one team can ship a feature to both platforms at once. The integration is well supported and genuinely production-proven — the craft is in the seams, and that is where this guide spends its time.

Key facts, with sources

  • React Native 0.76, released October 23, 2024, enabled the New Architecture by default and shipped with over 1,070 commits from 156 contributors plus a roughly 15x faster Metro resolver. (React Native official blog)
  • The State of React Native 2024 survey collected 3,501 responses, up from about 2,400 the previous year, covering more than 15 areas of the ecosystem. (State of React Native survey)
  • About 20% of State of React Native 2024 respondents reported apps with more than 100,000 users, up from 14% the year before. (InfoQ)
  • Shopify migrated all of its mobile apps to React Native over five years and reports sub-500ms (P75) screen loads and over 99.9% crash-free sessions in production. (Shopify Engineering)
  • 88% of surveyed React Native developers feel the framework is progressing positively, while better debugging remains the top request, cited by 54% of respondents. (SSOJet (State of React Native 2024 highlights))

When brownfield is the right call

Brownfield fits three situations. First, incremental migration: you intend to move to React Native over time and need to ship migrated flows inside the existing app rather than betting on a rewrite. Second, feature velocity inside a native app that is not going anywhere: a large established app wants one team to build certain product areas — promotions, help centers, checkout experiments, content feeds — once for both platforms. Third, organizational reality: you have strong web/React talent and thin native bench, and brownfield lets that talent ship mobile features safely inside a native shell.

It is the wrong call when the app is small enough that a full React Native rebuild is cheaper than maintaining the seam, or when the flows you would embed are exactly the platform-heavy ones — camera pipelines, real-time media — where React Native adds a layer without adding leverage. The seam has a fixed cost; make sure enough feature work flows through it to pay that cost back.

Architecture: React Native as a guest, not the host

The load-bearing decision is that the native app remains the host. Native code owns app startup, root navigation, authentication, deep links, and push handling; React Native provides screens or flows that mount inside native view controllers and activities. Resist the temptation to hand React Native the navigation stack early — mixed navigation ownership is the single largest source of brownfield jank, back-button bugs, and memory surprises.

Define the boundary as an explicit contract: which flows are React Native, what context each receives at mount (session, user, theme, locale), what events it can emit back to the host (flow completed, navigation requests, analytics), and which capabilities it accesses through native modules. Treat that contract like a public API with versioning discipline, because two teams with different release rhythms will build against it. A boring, well-documented seam is the difference between a brownfield app and a haunted one.

Entry points: registering flows and typing their props

On the JavaScript side, each embeddable flow registers under a stable name with AppRegistry — the same mechanism a greenfield app uses for its single root, used multiple times. The native host mounts a React Native view by that name and passes initial properties, which arrive as props on your root component. Keep those props primitive and serializable: tokens, IDs, enums — never rich objects, and never data that goes stale, which should be fetched or read through a native module instead.

I keep every registered flow in one entry file, with the prop contracts as exported TypeScript types that double as the documentation the native team reads. One registration detail worth knowing: multiple flows can share one React Native instance and bundle, so registering several flows costs little beyond the first.

Registering embeddable flows with typed prop contracts
import { AppRegistry } from 'react-native';
import { OrdersFlow } from './src/flows/OrdersFlow';
import { HelpCenterFlow } from './src/flows/HelpCenterFlow';

// Prop contracts for the native host -- passed as initialProperties
// when the host mounts each flow, arriving as root component props.
export type OrdersFlowProps = {
  sessionToken: string;
  userId: string;
  theme: 'light' | 'dark';
  locale: string;
};

export type HelpCenterFlowProps = {
  sessionToken: string;
  articleId?: string; // deep-link target, optional
};

AppRegistry.registerComponent('OrdersFlow', () => OrdersFlow);
AppRegistry.registerComponent('HelpCenterFlow', () => HelpCenterFlow);

Sharing auth, session, and design context

The cardinal brownfield sin is duplicating authentication — a React Native flow with its own login or its own token refresh will drift from the host and generate the class of bug where half the app thinks the user is logged out. The host app owns the session; React Native receives a token at mount via initial properties and, for anything longer-lived, reads current credentials through a small native module that exposes the host's session manager. Token refresh stays native, in exactly one place.

The same principle covers visual and locale context: pass theme and locale at mount, and emit events from native when they change so mounted flows update live rather than showing a stale theme after the user toggles dark mode in native settings. Consistency here is what makes embedded flows feel like the same app instead of a webview with better performance — matching navigation transitions, typography scale, and haptic behavior is unglamorous work that users absolutely notice when it is missing.

Build and bundle integration

The seam you will maintain forever is the build. The native app's build must produce or consume the JavaScript bundle: in debug, developers run Metro and the app loads from it with fast refresh working inside the native app; in release, bundling runs as a build phase and the bundle ships inside the binary. Getting both modes reliable — including for native developers who do not have the JS toolchain warmed up — is the difference between a team that likes the setup and one that resents it.

Dependency integration is the other half: CocoaPods and Gradle pull in React Native and every native module your JS side uses, which means JS dependency changes can alter the native build. Lock versions ruthlessly, document the one-command setup, and put a CI job on the matrix that builds the native app with the current bundle on every relevant PR — seam breakage discovered at release time is the canonical brownfield failure.

Team workflow pitfalls I warn every client about

The recurring failures are organizational. Unclear ownership of the seam: when the bridge code, native modules, and build integration belong to 'both teams,' they belong to neither — assign an owner. Diverging release rhythms: the JS side can ship faster than native store releases, which is a feature, but only if the prop and event contracts stay backward compatible; version them and test old-host-new-bundle combinations. Silent capability assumptions: JS developers adding a library with native code without realizing it changes the host build — catch this in review and CI, not in a broken release branch.

And measure the embedded flows separately: crash rates, cold mount time, and memory for React Native screens versus native ones, because the first regression will otherwise be discovered by users. Teams that treat the boundary as a product — owned, versioned, monitored — ship happily for years. Teams that treat it as glue code get exactly what they maintain.

When to hire senior help

Bring in senior React Native help when facing a New Architecture or major version migration, persistent performance regressions, or a first store launch, since these are the phases where inexperienced teams lose the most months. A short senior architecture audit early in the project is consistently cheaper than a rescue or rewrite later. If your stack includes React Native + Python + AI, a senior engineer who owns the full product beats coordinating multiple juniors.

Bottom line

Dhairya Senjaliya ships Mobile — React Native Development projects worldwide — book a scoping call to discuss your specific situation.

Common pitfalls to avoid

  • Staying multiple versions behind on React Native, then facing a compound upgrade to the New Architecture because popular libraries have dropped old-architecture support
  • Treating React Native as write-once-run-anywhere and only QA-testing on iOS, shipping Android builds with broken back-button handling, keyboard behavior, and gesture bugs
  • Pulling in unmaintained third-party native modules without checking TurboModule and Fabric compatibility, which later blocks the New Architecture migration
  • Launching without crash and performance monitoring wired in, so the team only discovers jank and crash clusters from one-star reviews instead of telemetry

Frequently asked questions

Can React Native be added to an existing native iOS or Android app?

Yes — this is called brownfield integration and it is a supported, production-proven pattern. The native app keeps its shell, navigation, and authentication, and mounts React Native views for specific flows, each registered by name via AppRegistry and receiving context like session tokens through initial properties. It is the standard path for incremental migrations and for adding cross-platform feature velocity to established native apps.

How does an embedded React Native flow get the user's login session?

Never by implementing its own login. The native host owns authentication and passes a session token as initial properties when mounting the flow; for longer-lived needs, the flow reads current credentials through a small native module exposing the host's session manager. Token refresh stays in exactly one place — the native side — which prevents the drift bugs where half the app disagrees about login state.

What is the hardest part of maintaining a brownfield React Native integration?

The build seam. Debug builds must load from Metro with fast refresh working inside the native app, release builds must bundle JavaScript as a build phase, and JS dependency changes can alter the native build through autolinked modules. Assign clear ownership of that seam, lock versions, and run CI that builds the native app with the current bundle — seam breakage found at release time is the classic brownfield failure.

Is React Native still a good technology bet in 2026?

Yes for teams with JavaScript or React skills; the New Architecture has been the default since version 0.76 in late 2024, and the framework is used in production by Meta, Microsoft, Shopify, and Amazon. In the latest State of React Native survey, 88% of developers said the framework is heading in a positive direction.

Can a React Native app feel as fast as a fully native app?

For most business, e-commerce, and content apps, yes; Shopify runs its entire app portfolio on React Native with sub-500ms P75 screen loads and over 99.9% crash-free sessions. Workloads like heavy 3D, AR, or real-time audio processing still warrant native modules or fully native builds.

How much code is actually shared between iOS and Android?

Production teams commonly report 85 to 95%+ shared code; published examples include Instagram at 85 to 99% and Shopify at roughly 86%. The remainder is platform-specific work such as payments, widgets, and deep OS integrations.

Bottom line: Dhairya Senjaliya ships Mobile — React Native Development projects worldwide. Book a scoping call at https://dhairyasenjaliya.com/#book-call.

Sources

Related guides

Keep up with new guides

New deep-dive guides on React Native, Python, and AI ship regularly. Subscribe via RSS or follow on LinkedIn.

Want help implementing this?

30-minute scoping call · Clear milestones · Senior engineer ownership