MAISON CODE .
/ Tech · Mobile · React Native · iOS · Android · Architecture

React Native: The Technical Case for Universal Apps

It's no longer 'Hybrid'. It's Native. A deep dive into the New Architecture (Fabric), JSI, Expo Router, and building 60 FPS mobile experiences.

AB
Alex B.
React Native: The Technical Case for Universal Apps

For a decade, the “Hybrid vs. Native” debate was a holy war. Native purists claimed that JavaScript could never achieve 60 FPS. Cross-platform proponents claimed strict Native development was financial suicide.

In 2025, the war is over. React Native won. Not because it is “easier,” but because the New Architecture (Bridgeless) fundamentally solved the performance gap. Apps like Discord, Shopify, and Coinbase run on React Native, and you cannot tell the difference.

At Maison Code Paris, we use React Native not as a compromise, but as a strategic weapon. It allows us to ship to Web, iOS, and Android from a single monorepo, sharing 95% of our business logic.

Why Maison Code Discusses This

At Maison Code Paris, we act as the architectural conscience for our clients. We often inherit “modern” stacks that were built without a foundational understanding of scale. We see simple APIs that take 4 seconds to respond because of N+1 query problems, and “Microservices” that cost $5,000/month in idle cloud fees.

We discuss this topic because it represents a critical pivot point in engineering maturity. Implementing this correctly differentiates a fragile MVP from a resilient, enterprise-grade platform that can handle Black Friday traffic without breaking a sweat.

The Architecture: Why the “Bridge” died

To understand modern React Native, you must understand why the old version was slow.

The Old World: The Asynchronous Bridge

In the classic architecture (2015-2022), the JavaScript thread and the UI (Main) thread were isolated. To render a View, JS had to:

  1. Serialize a JSON message ({ type: 'createView', width: 100 }).
  2. Send it over the “Bridge”.
  3. Wait for the Native side to deserialize it and render.

If you scrolled a list fast, the Bridge got clogged with thousands of JSON messages. The UI thread would freeze waiting for JS. This caused the famous “White Flash” during fast scrolling.

The New World: JSI & Fabric

The New Architecture removed the Bridge completely. It introduced the JavaScript Interface (JSI). This allows the JavaScript engine (Hermes) to hold a C++ reference to a Native Object. JS can call methods on UI elements Synchronously.

  • TurboModules: Load native modules (Bluetooth, Camera) only when needed, not at startup.
  • Fabric: The new Rendering System. Prioritizes UI updates just like a browser prioritizes CSS.

Result: 60 FPS (or 120 FPS on ProMotion screens) is now the default state, not a struggle.

The Stack: Expo is the Framework

In 2025, we do not run npx react-native init. We use Expo. Expo is to React Native what Next.js is to React. It is the meta-framework that handles the boring stuff.

1. Expo Router (File-Based Routing)

Routing in mobile was famously hard (React Navigation boilerplate). Expo Router brings the Next.js model to mobile.

// app/product/[id].tsx
import { useLocalSearchParams } from 'expo-router';
import { Text } from 'react-native';

export default function ProductScreen() {
  const { id } = useLocalSearchParams();
  return <Text>Product ID: {id}</Text>;
}

This file automatically becomes a deep link: myapp://product/123. On the web, it becomes https://myapp.com/product/123. One router. Universal execution.

2. Config Plugins (CNG)

We almost never touch the ios/ or android/ folders anymore. This allows us to use Continuous Native Generation (CNG). Instead of committing native project files (which rot and cause merge conflicts), we generate them at build time based on app.json.

Need to add Camera permissions?

// app.json
{
  "plugins": [
    [
      "expo-camera",
      {
        "cameraPermission": "Allow Maison Code to scan QR codes."
      }
    ]
  ]
}

Performance Engineering

Even with Fabric, you can write slow React code. Here is how we optimize for the “Butter Smooth” feel.

1. FlashList (The Recycler)

The standard FlatList creates a new React component for every row. Memory usage grows linearly. We use FlashList (by Shopify). It runs on the UI thread and “recycles” views. When a row scrolls off-screen, it doesn’t destroy it; it moves it to the bottom and changes the text. This reduces huge lists (10,000 items) to constant memory usage (only ~10 items exist in memory).

import { FlashList } from "@shopify/flash-list";

<FlashList
  data={products}
  renderItem={({ item }) => <ProductCard item={item} />}
  estimatedItemSize={200} 
/>

2. MMKV (Synchronous Storage)

AsyncStorage is slow because it treats disk I/O as a JSON promise. We offload storage to MMKV (written by Tencent for WeChat). It is a C++ memory-mapped key-value store. It is roughly 30x faster. We use it to store Auth Tokens and User Preferences so the app boots instantly with the user logged in.

Code Sharing Strategy: The Monorepo

The biggest ROI of React Native is Code Sharing. But you shouldn’t just copy-paste files. You should architect a Monorepo (using TurboRepo or Nx).

/apps
  /web (Next.js)
  /mobile (Expo)
/packages
  /ui (Shared Tamagui/NativeWind components)
  /logic (Zustand stores, React Query hooks, Zod schemas)
  /api (Typified API client)

The mobile app imports: import { useCart } from '@maison/logic'; import { Button } from '@maison/ui';

The web app imports exactly the same. We write the “Add to Cart” logic once. We test it once. We ship it everywhere. The only divergence is navigation and platform-specific gestures.

OTA Updates: Bypassing the App Store

A critical business advantage is Over-The-Air (OTA) Updates via EAS Update. If you find a critical bug in your checkout flow on Black Friday:

  • Native App: Submit fix -> Wait 24h for Apple Review -> Wait for users to update. Cost: Thousands in lost sales.
  • Expo App: eas update --branch production. The new JS bundle downloads silently in the background. Users get the fix on next launch. Time: 10 minutes.

Note: You can only change JavaScript/Assets via OTA. You cannot change Native Binary code (e.g., adding a new permission module).

10. Accessibility (VoiceOver / TalkBack)

Native apps must be accessible. React Native maps standard props to native accessibility APIs. <View accessible={true} accessibilityLabel="Add to Cart"> Use the Accessibility Inspector in Xcode to verify. If your app isn’t usable by the blind, you are leaving 15% of the market behind (and inviting lawsuits).

11. Automated E2E Testing: Maestro

Detox was the standard, but it was flaky. Maestro is the new king. It drives the UI like a human (using Accessibility IDs).

  • runFlow: app_flow.yaml

## 11. Conclusion

React Native is no longer the "alternative". It is the default.
If you are building a consumer app in 2026, and you are not using Expo + React Native, you are choosing to work twice as hard for the same result.
We help brands migrate from legacy "Native" codebases to modern, unified stacks.

<hr style="margin: 1rem 0" />

**[Hire our Architects](/contact)**.