Skip to content
iPhone Duo SupportGet help

React Native on iPhone Duo: what breaks and what works

Ingenious Techlab Team

Engineering analysis, not vendor guidance

React Native has not shipped iPhone Duo support or published guidance for it. Everything below is our analysis of how React Native behaves against the APIs and behaviours Apple has documented. Treat the Apple-side facts as authoritative and the React Native-side conclusions as reasoned inference to verify against your own app.

Meta has not shipped iPhone Duo support and has published no guidance for it. Everything below is our analysis of how React Native behaves against the APIs and behaviours Apple documented on 9 September 2026. The Apple-side facts are sourced; the React Native conclusions are reasoned inference you should verify against your own build.

The short version: React Native apps will mostly work, because flexbox is inherently adaptive. Three specific patterns break, and one capability is out of reach without native code.

Why the baseline is better than you would expect

Under the hood, a React Native view hierarchy is a native view hierarchy. When iPhone Duo unfolds, UIKit resizes the root view, and Yoga relayouts everything inside it. An app built with flex ratios rather than fixed pixel values adapts without a single line of change.

That is genuinely most apps. Which makes the failures worth knowing precisely, because they are narrow.

Break one: cached dimensions

This is the big one, and it is nearly universal.

// Broken on iPhone Duo — evaluated once, at module load
const { width } = Dimensions.get('window');

const styles = StyleSheet.create({
  card: { width: width - 32 },
});

That width was captured at launch. On iPhone Duo it becomes wrong when the user unfolds the device, folds it closed, rotates it, or resizes Split View. The style object is created once and never recomputed, so the card keeps its launch-time width forever.

The fix is the hook, which re-renders on change:

function Card({ children }) {
  const { width } = useWindowDimensions();
  return <View style={{ width: width - 32 }}>{children}</View>;
}

Worth searching for specifically, since the module-scope form is invisible in review:

grep -rn "Dimensions.get" src/

Every hit outside a component render is suspect. Note that Dimensions.addEventListener is a partial fix at best — it fires, but a StyleSheet.create object built at module load will not be rebuilt by it.

There is a subtler variant worth checking: percentage-of-screen constants like const CARD = width * 0.45. These read as responsive and are not.

Break two: orientation locking

Many React Native apps lock to portrait, in Info.plist or through a library. Apple states the inner display does not honor supported interface orientations.

So the lock silently stops working, and your app is laid out in configurations it was never designed for. If your layout assumed width is always less than height, that assumption is gone.

The replacement is not another lock. It is a layout that works at any aspect ratio:

const { width, height } = useWindowDimensions();
const isWide = width > 600;

return isWide ? <TwoColumn /> : <SingleColumn />;

A width of 600 is a reasonable dividing line here: the inner display is 626 points wide and the outer is 466.

Break three: collapsed safe area insets

react-native-safe-area-context reports the real insets. The problem is what application code does with them.

// Common, and now wrong
const insets = useSafeAreaInsets();
<View style={{ paddingHorizontal: Math.max(insets.left, insets.right) }} />

Apple is explicit that safe areas are asymmetric on iPhone Duo. Taking the max, or applying one horizontal value to both edges, was harmless when the two matched. It now over-pads one side, and content drifts off-centre.

<View style={{ paddingLeft: insets.left, paddingRight: insets.right }} />

SafeAreaView handles this correctly on its own. The bugs are in hand-rolled inset math.

What you cannot reach

Here is the honest limitation. These have no JavaScript bindings today:

Reaching any of them means a native module wrapping the Swift API and bridging values into JS. For reserved regions that is a moderate piece of work: a native view that queries reservedRegions(kind:), observes changes, and emits frames as props.

Until someone ships that, a React Native app can be correct on iPhone Duo but not hinge-aware. It can lay out properly at any size; it cannot avoid placing a button on the fold.

For most content apps — feeds, commerce, messaging, media — correctness is the whole job, and the fold falls in a place users tolerate. For a canvas, an editor, a drawing app, or a game board, the fold matters and you should budget for native work.

What you get for free that is worth using

The inner display is regular-width in both dimensions, with room for a sidebar. If your app has a tablet layout behind a breakpoint, it will now appear on a phone, and it is probably the right layout. Check that your breakpoint is driven by live dimensions rather than by a device-type check:

// Wrong — Platform.isPad is false on iPhone Duo
const isTablet = Platform.OS === 'ios' && Platform.isPad;

// Right
const { width } = useWindowDimensions();
const isWide = width >= 600;

Any device-info library used to pick a layout has this same problem.

Split View, and the freeze bug

All apps participate in side-by-side multitasking on iPhone Duo — there is no opt-in. Two things to check:

Continuous resize. Dragging the Split View divider changes your width continuously. useWindowDimensions handles it; cached values do not.

AppState. In Split View your app can be visible but not active. Code that stops video, timers, or animation on AppState changing to inactive will look frozen to a user who can still see the window. This pattern is common in React Native for battery reasons, and it is worth revisiting for this device specifically.

A pragmatic migration

  1. grep -rn "Dimensions.get" — replace every module-scope call with useWindowDimensions
  2. Remove orientation locks and fix whatever they were hiding
  3. Audit useSafeAreaInsets consumers for symmetric math
  4. Replace device-type layout checks with width checks
  5. Test the Split View divider through its full range
  6. Verify AppState handling does not freeze visible content
  7. Decide whether the fold matters enough for a native module

Steps 1 to 4 are a day’s work in most codebases and account for nearly all of the visible improvement.

What would change this analysis

If React Native ships a useDisplayFeatures-style API bridging Apple’s reserved regions, the last section becomes obsolete and hinge-aware layout becomes reachable in JS. Nothing has been announced. We will update this post if that changes — it is dated and versioned above.

Related

Want this done for you?

We add iPhone Duo and adaptive-layout support to existing iOS apps, native and cross-platform.