Skip to main content
React Native makes it easy to write code that works on both iOS and Android, but sometimes you need platform-specific logic. This guide covers the various ways to handle platform differences.

The Platform Module

The Platform module from React Native provides information about the current platform.

Platform.OS

Check which platform your code is running on:
import {Platform, Text} from 'react-native';

function PlatformInfo() {
  return (
    <Text>
      Running on {Platform.OS}
    </Text>
  );
}

// Platform.OS returns: 'ios' | 'android' | 'windows' | 'macos' | 'web'

Platform.Version

Get the platform version:
import {Platform} from 'react-native';

// Returns iOS version as string (e.g., "14.5")
console.log(Platform.Version); // "15.0"

if (parseFloat(Platform.Version) >= 14) {
  // Use iOS 14+ features
}

Platform Implementation from Source

From the React Native source code:
// From Libraries/Utilities/Platform.ios.js
const Platform = {
  OS: 'ios',
  get Version(): string {
    return this.constants.osVersion;
  },
  get isPad(): boolean {
    return this.constants.interfaceIdiom === 'pad';
  },
  get isTV(): boolean {
    return this.constants.interfaceIdiom === 'tv';
  },
  get isVision(): boolean {
    return this.constants.interfaceIdiom === 'vision';
  },
};

Platform.select()

Return different values based on platform:
import {Platform, StyleSheet} from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    ...Platform.select({
      ios: {
        backgroundColor: 'white',
        shadowColor: '#000',
        shadowOffset: {width: 0, height: 2},
        shadowOpacity: 0.3,
      },
      android: {
        backgroundColor: '#f5f5f5',
        elevation: 4,
      },
    }),
  },
});

Platform.select() with Components

import {Platform, TouchableOpacity, TouchableNativeFeedback} from 'react-native';

const Touchable = Platform.select({
  ios: TouchableOpacity,
  android: TouchableNativeFeedback,
});

function MyButton({children, onPress}) {
  return (
    <Touchable onPress={onPress}>
      {children}
    </Touchable>
  );
}

Real Example from React Native Source

From Libraries/Components/Button.js:
Button.js (source)
const styles = StyleSheet.create({
  button: Platform.select({
    ios: {},
    android: {
      elevation: 4,
      backgroundColor: '#2196F3',
      borderRadius: 2,
    },
  }),
  text: {
    textAlign: 'center',
    margin: 8,
    ...Platform.select({
      ios: {
        color: '#007AFF',
        fontSize: 18,
      },
      android: {
        color: 'white',
        fontWeight: '500',
      },
    }),
  },
});

Platform-Specific File Extensions

Create separate files for each platform:
1

Create platform-specific files

MyComponent.ios.js
MyComponent.android.js
2

Import without extension

import MyComponent from './MyComponent';
React Native automatically picks the right file based on platform.

Example: Platform-Specific Components

import {View, Text} from 'react-native';

export default function MyComponent() {
  return (
    <View>
      <Text>iOS Version</Text>
      {/* iOS-specific implementation */}
    </View>
  );
}

Real Example from React Native

From the React Native source, ToastAndroid has platform-specific implementations:
ToastAndroid.js          # Base file with type definitions
ToastAndroid.ios.js      # iOS (shows warning)
ToastAndroid.android.js  # Android (actual implementation)

Platform-Specific Props

Some components have platform-specific props:
import {TextInput} from 'react-native';

<TextInput
  clearButtonMode="while-editing"  // iOS only
  enablesReturnKeyAutomatically    // iOS only
  dataDetectorTypes="phoneNumber"  // iOS only
/>

Conditional Rendering

import {View, Text, Platform} from 'react-native';

function Header() {
  return (
    <View>
      <Text>My App</Text>
      {Platform.OS === 'ios' && (
        <Text style={{fontSize: 12}}>iOS Exclusive Feature</Text>
      )}
      {Platform.OS === 'android' && (
        <Text style={{fontSize: 12}}>Android Exclusive Feature</Text>
      )}
    </View>
  );
}

Platform-Specific APIs

Some APIs are platform-specific:
import {ActionSheetIOS, Alert} from 'react-native';

// ActionSheetIOS
if (Platform.OS === 'ios') {
  ActionSheetIOS.showActionSheetWithOptions(
    {
      options: ['Cancel', 'Delete'],
      destructiveButtonIndex: 1,
      cancelButtonIndex: 0,
    },
    (buttonIndex) => {
      console.log('Button clicked:', buttonIndex);
    }
  );
}
import {ToastAndroid, Platform} from 'react-native';

// ToastAndroid
if (Platform.OS === 'android') {
  ToastAndroid.show('Message sent!', ToastAndroid.SHORT);
}

// PermissionsAndroid
import {PermissionsAndroid} from 'react-native';

async function requestCameraPermission() {
  if (Platform.OS === 'android') {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.CAMERA
    );
    return granted === PermissionsAndroid.RESULTS.GRANTED;
  }
  return true; // iOS handles permissions differently
}

Styling Differences

Shadows vs Elevation

const styles = StyleSheet.create({
  card: {
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
  },
});

Device-Specific Code

Check for iPad

import {Platform} from 'react-native';

if (Platform.OS === 'ios' && Platform.isPad) {
  console.log('Running on iPad');
}

Check for TV

import {Platform} from 'react-native';

if (Platform.isTV) {
  console.log('Running on TV');
}

Best Practices

Use Platform.select() for styles

Keeps your code clean and readable when differences are minor

Use .ios.js/.android.js for major differences

Better for completely different implementations

Test on both platforms

Always test platform-specific code on actual devices

Document platform differences

Comment why platform-specific code is needed

Common Patterns

Safe Area Handling

import {SafeAreaView, View, Platform, StatusBar, StyleSheet} from 'react-native';

function App() {
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.content}>
        {/* Your app content */}
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,
  },
  content: {
    flex: 1,
  },
});
import {Platform} from 'react-native';

const NAVBAR_HEIGHT = Platform.select({
  ios: 44,
  android: 56,
  default: 56,
});

Next Steps

Networking

Learn about fetching data from APIs

Navigation

Navigate between screens in your app

Build docs developers (and LLMs) love