In React Native, how do Platform.isPad, Platform.isTV and Platform.isVision decide the device type, and what do they return on Android?
answer
- iOS reads constants.interfaceIdiom
- 'pad', 'tv', 'vision' idioms
- Android isTV reads uiMode
- Android isVision is always false
- isPad exists only on iOS
basics
~10 sOn iOS all three compare Platform.constants.interfaceIdiom with 'pad', 'tv' or 'vision'. On Android isTV checks uiMode === 'tv', isVision is always false, and isPad does not exist, so it reads as undefined.
solid answer
~30 sOn iOS, React Native derives all three from `Platform.constants.interfaceIdiom`, the device's interface idiom: `isPad` is `'pad'`, `isTV` is `'tv'`, `isVision` is `'vision'`. An iPad app running on Apple Vision Pro in its iPad-compatible mode reports `isVision` `false` and `isPad` `true`. On Android, `isTV` compares `Platform.constants.uiMode` with `'tv'`, `isVision` is hard-coded to `false`, and there is **no `isPad`**, so reading it gives `undefined`; React Native's TypeScript types only allow it after narrowing `Platform.OS` to `'ios'`. These flags describe the device, not the window, so an iPad in Split View is still `isPad`; size decisions belong to window dimensions.
code
typescript · 10 linesimport { Platform } from 'react-native';
// isPad exists only on the iOS member of the Platform union
export const isIPad = Platform.OS === 'ios' && Platform.isPad;
export const isTV = Platform.isTV;
// Android has no tablet flag: decide from the window width instead
export function isTabletWidth(windowWidth: number): boolean {
return windowWidth >= 600;
}go deeper
Recall that isPad, isTV and isVision are booleans on Platform, and that isPad is an iOS-only property.
Explain the sources: iOS interfaceIdiom for all three, Android uiMode for isTV, isVision always false on Android, and the Vision Pro iPad-compatibility case.
Keep device flags for behaviour, such as TV focus navigation, and use window size for layout, centralizing both so tablets, foldables and Split View behave consistently.
Decide which form factors the product supports and encode that as a small device capability module, rather than letting screens branch on raw Platform flags.
## Device-type flags on Platform Besides `Platform.OS`, React Native's `Platform` module exposes boolean getters for the kind of device: `isPad`, `isTV` and `isVision`. They are computed from `Platform.constants`, an object React Native reads once from a native module and caches. ## iOS: one field, three flags On iOS the native side reports the device's **interface idiom** as `Platform.constants.interfaceIdiom`, a string. The three flags are simple comparisons: 1. `Platform.isPad` is `interfaceIdiom === 'pad'`; 2. `Platform.isTV` is `interfaceIdiom === 'tv'`; 3. `Platform.isVision` is `interfaceIdiom === 'vision'`. React Native's docs call out one subtlety: an app running on Apple Vision Pro as an iPad app ("Designed for iPad") reports `isVision` as `false` and `isPad` as `true`, because the system presents it with the iPad idiom. Only an app running natively with the vision idiom sees `isVision` as `true`. ## Android: different sources, fewer flags Android has no interface idiom, so the flags work differently: - `Platform.isTV` compares `Platform.constants.uiMode` with `'tv'`. `uiMode` can be `'car'`, `'desk'`, `'normal'`, `'tv'`, `'watch'` or `'unknown'`. - `Platform.isVision` is always `false`. - `Platform.isPad` **does not exist**. Reading it at runtime yields `undefined`, which is falsy, so code that only tests truthiness still behaves, but the value is not a boolean. | Flag | iOS source | Android | |---|---|---| | `isPad` | `interfaceIdiom === 'pad'` | not defined, `undefined` | | `isTV` | `interfaceIdiom === 'tv'` | `uiMode === 'tv'` | | `isVision` | `interfaceIdiom === 'vision'` | always `false` | React Native's TypeScript types reflect this: `Platform` is a union discriminated by `OS`, and only the iOS member declares `isPad`. `Platform.isPad` therefore fails to type-check until you narrow with `Platform.OS === 'ios'`, which is the compiler telling you there is no Android tablet flag. ## What else is in Platform.constants `Platform.constants` is also the place for other device facts: - on both platforms: `reactNativeVersion` (`major`, `minor`, `patch`, optional `prerelease`) and `isTesting`; - on iOS: `osVersion`, `systemName`, `interfaceIdiom`, `forceTouchAvailable`, and `isMacCatalyst` where it applies; - on Android: `Version` (the API level), `Release`, `Model`, `Brand`, `Manufacturer`, `Fingerprint`, `uiMode` and a few more. `Platform.isTesting` returns the native flag only in development builds; in a release build it is always `false`. ## When the values are available All of these are synchronous getters. The first read of `Platform.constants` fetches the object from a native module and caches it; later reads, including `isPad`, `isTV` and `isVision`, are plain property lookups. They are available at module scope, before the first render, so it is safe to compute a module-level constant such as `const isIPad = Platform.OS === 'ios' && Platform.isPad`. They do not change while the process runs, which is exactly why they are unsuitable for anything that does change, such as the window size. ## A weather app example Suppose the weather app ships on phones, tablets and a TV build. The TV build needs focusable forecast tiles and larger type for viewing from across a room, which is a behaviour branch keyed on `Platform.isTV`. The tablet layout, a two-column forecast, is not a device question at all: it depends on how wide the window is right now, so it reads the window width and switches columns when an iPad enters Split View or an Android foldable opens. `Platform.isPad` is left for the rare iPad-only behaviour, such as a pointer hover affordance. ## Using the flags well - **Device type is not window size.** An iPad in Split View or Slide Over is still `isPad`, and a large Android tablet has no flag at all. For layout, such as showing a two-column forecast, read the current window dimensions instead of a device flag. - **Tablet detection on Android is a size question.** Since there is no `isPad`, teams decide from window width, which also handles foldables and resizable windows. - **TV and vision change interaction, not just size.** `isTV` is the signal to support focus-based navigation with a remote; `isVision` to adjust for a spatial display. Those are real behaviour branches, which is where the flags earn their keep. - **Keep the checks central.** A small `device.ts` that exports `isTablet(width)` and `isTV` stops `Platform.isPad` from being sprinkled through screens.
- Why is Platform.isPad a poor signal for a two-column forecast layout in a React Native weather app?`isPad` reports the device idiom, not the space the app has. An iPad in Split View is still `isPad` with a narrow window, and Android tablets have no `isPad` at all. Base the column count on the current window width, which updates when the window resizes, and keep `isPad` for genuinely device-specific behaviour.
- What does React Native's Platform.isTesting return in a release build?Always `false`. The getter only returns the native `isTesting` constant when `__DEV__` is true, so test-only branches keyed on it cannot activate in production builds.
saying these in an interview costs you the question
- Platform.isPad returns true on Android tablets.
- Platform.isVision is true for any iPad app running on Vision Pro.
- Platform.isPad turns false when an iPad app is in Split View.
- Platform.isTV only works on iOS.
- Platform.isPad can be read without narrowing Platform.OS in TypeScript.