# React Native on iPhone Duo: what breaks and what works > Meta has shipped no iPhone Duo support. Which React Native patterns break on the foldable display, which survive, and where a native module becomes unavoidable. Source: https://iphoneduosupport.com/blog/react-native-iphone-duo/ Published: 2026-09-09 Framework: react-native Status: ENGINEERING ANALYSIS — this framework vendor has published no iPhone Duo guidance. Apple-side facts are sourced; framework-side conclusions are inference. Sources: https://developer.apple.com/videos/play/tech-talks/111461/ https://developer.apple.com/videos/play/tech-talks/111463/ https://developer.apple.com/videos/play/tech-talks/111464/ Last verified: 2026-09-09 --- 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. ```jsx // 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: ```jsx function Card({ children }) { const { width } = useWindowDimensions(); return {children}; } ``` Worth searching for specifically, since the module-scope form is invisible in review: ```bash 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: ```jsx const { width, height } = useWindowDimensions(); const isWide = width > 600; return isWide ? : ; ``` 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. ```jsx // Common, and now wrong const insets = useSafeAreaInsets(); ``` 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. ```jsx ``` `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: - `ReservedRegion` — where the hinge divides the display - `ArrangementView` — pose-aware primary/secondary placement - `onHingeChange` — hinge angle - Scene accessories — content on the outer display while the app runs on the inner - The vertical toolbar APIs — `axisBehavior`, `visibilityPriority`, and the rest 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: ```jsx // 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. --- Published by iPhone Duo Support (https://iphoneduosupport.com). Not affiliated with Apple Inc.