React Native — Platform specific code
Tags: reactnative, platformmodule
Published: 2018-05-13 06:01:41

---
title: React Native — Platform specific code
published: true
tags: react-native, platform module
canonical_url: https://medium.com/maestral-solutions/react-native-platform-specific-code-e217db5778f
cover_image: https://thepracticaldev.s3.amazonaws.com/i/joxbqv0vtnf9zwbygcut.png
---

With React Native we are writing the code for both, iOS and Android. And it won’t pass long to notice that we need to differ one from another.

![](https://cdn-images-1.medium.com/max/353/1*27A-seCkORB2P4QyEWIZUQ.png)

![](https://cdn-images-1.medium.com/max/405/1*zsngww4SLJp5W5CcwD2xvg.png)

![](https://cdn-images-1.medium.com/max/274/1*q6svgsA7XjoEX1t2zUw-BQ.png)<figcaption>Right: Android Emulator Nexus 5 API 23 1080x1920: xxhdpi x86_64</figcaption>

As we can see, our _Header_ component, that has the simple task of displaying text behaves differently on Android and iOS. Clearly, we need to have two different styles for the two. So, how can we accomplish this? Good people from the React Native team have provided us with a quite simple solution. They have offered us a module called **_Platform_**.

All we need to do is to import _Platform_ from _react-native_ and we are good to go. The _Platform_ has **_OS_** property which tells us either we are running our app on **_iOS (ios)_** or **_Android (android)_**. Furthermore, _Platform_ comes with a method _select_ which given an object with a key of _Platform.OS_ will return the value for the platform we are running our code on.

Enough talk. Let’s see those in action.

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

export const Header = () => (
  <View style={styles.header}>
    <Text style={styles.text}>I am Header</Text>
  </View>
);

const styles = StyleSheet.create({
  header: {
    height: Platform.OS === 'android' ? 76 : 100,
    marginTop: Platform.OS === 'ios' ? 0 : 24,
    ...Platform.select({
      ios: { backgroundColor: '#f00', paddingTop: 24},
      android: { backgroundColor: '#00f'}
    }),
    alignItems: 'center',
    justifyContent: 'center'
  },
  text: {
    color: '#fff',
    fontSize: 24
  }
});
```

And the result of running such code:

![](https://cdn-images-1.medium.com/max/558/1*F4oppM9YhvpThAadRb9LDQ.png)<figcaption>Header after style applied</figcaption>

Let’s break down our code!

```
height: Platform.OS === 'android' ? 76 : 100,
marginTop: Platform.OS === 'ios' ? 0 : 24,
```

Nothing fancy here. We have already mentioned that _Platform.OS_ returns _ios_ or _android_ depending on the platform it is running on. Combining that with the ternary operator gave us this nice code which helped us set height/margin of our _Header_. This code is equivalent to `height: 76, marginTop: 24` on Android and `height:100, marginTop: 0` on iOS

Moving along we have:

```
...Platform.select({
 ios: { backgroundColor: '#f00', paddingTop: 24},
 android: { backgroundColor: '#00f'}
 }),
```

As we mentioned _Platform.select_ will return the value given the key from _Platform.OS_. So in our case this code becomes `...{ backgroundColor: '#f00', paddingTop: 24}` for iOS, and `...{ backgroundColor: '#00f'}` for Android.

So to sum it up, or styles are going to look like this:

```
Android:
const styles = StyleSheet.create({
 header: {
 height: 76,
 marginTop: 24,
 backgroundColor: '#00f',
 alignItems: 'center',
 justifyContent: 'center'
 },
 text: {
 color: '#fff',
 fontSize: 24
 }
});

-----------------------------------

iOS:
const styles = StyleSheet.create({
 header: {
 height: 100,
 marginTop: 0,
 backgroundColor: '#f00', 
 paddingTop: 24,
 alignItems: 'center',
 justifyContent: 'center'
 },
 text: {
 color: '#fff',
 fontSize: 24
 }
});
```

We have not come to an end with _Platform.select_. The cool thing about it is that it accepts any value, so you can use this to your advantage to return components for iOS/Android. In our case, we have created _BodyAndroid.js, BodyIOS.js, and Body.js_. We have replaced default text in _App.js_ with _Body_ component. So, our _App.js_ look like this:

```
import React from 'react';
import { View} from 'react-native';
import {styles} from "./src/theme/Style";
import { Header } from './src/components/Header';
import { Body } from "./src/components/Body";

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Header />
        <Body />
      </View>
    );
  }
}
```

The rest of our code:

```
BodyAndroid.js
import React from 'react';
import { View, Text} from 'react-native';
import {styles} from "../theme/Style";

export const BodyAndroid = () => (
  <View style={styles.body}>
    <Text style={styles.h1}>This is Android App!</Text>
  </View>
);
--------------------------------
BodyIOS.js
import React from 'react';
import { View, Text} from 'react-native';
import {styles} from "../theme/Style";

export const BodyIOS = () => (
  <View style={styles.body}>
    <Text style={styles.h1}>This is iOS App!</Text>
  </View>
);
--------------------------------
Body.js
import { Platform } from 'react-native';

import { BodyAndroid } from './BodyAndroid';
import { BodyIOS } from './BodyIOS'

export const Body = Platform.select({
  ios: BodyIOS,
  android: BodyAndroid
});
```

And the result:

![](https://cdn-images-1.medium.com/max/510/1*-jQkLNSm62SMjnpSB_zOQg.png)

As good as this looks I do not consider it the best solution. There is something called **_Platform-specific extension_** which I prefer. So in the case of iOS, we want to have `.ios.` extension, while for Android we will have `.android.`. This will help React Native determine which component to use for what platform.

Let’s illustrate this with an example.

![](https://cdn-images-1.medium.com/max/353/1*bNqv2IwY33y28DWwCw_WlQ.png)

![](https://cdn-images-1.medium.com/max/660/1*0D5GGp57xaqUKxfZTbgRPg.png)

![](https://cdn-images-1.medium.com/max/274/1*vOY86XGPoRv2OveCzL3MjQ.png)

The code for our _Footer_ is very similar to our _Header,_ therefore, I will not be pasting it here. What is important for us to nice is this simple line `import { Footer } from './src/components/Footer';`. As we can notice in the components directory we do not have Footer file, but righter _Footer.ios_ and _Footer.android_. React Native is smart enough to determine which one to use, depending on what platform we are building our app for.

We have seen how we can add our component using the _Platform-specific_ extension and _Platform.select_ method. Was it all that _Platform module_ can do? Well, no. There is one more thing left and you might have guessed it. It is detecting the version of Android/iOS. So let’s modify our Body message by appending to it the version number.

![](https://cdn-images-1.medium.com/max/528/1*J-WyBmyljd0UgkcHo7UEvQ.png)

Showing _Platform_ version is as simple as calling **_Platform.Version_**. Well… there is a catch. While Android returns the version as an integer, iOS is not so friendly and will give us the version as a string. It should not be difficult to covert it to the integer if we need to compare it (which is the most likely scenario if we need a version number). If we just want to display it we are safe to go with what we get.

To make everything more interesting, React Native comes with build in components and APIs, some of which are Android/iOS specific. To mention few, for Android we have: _DatePickerAndroid, ProgressBarAndroid, ViewPagerAndroid_; as for iOS we have: _AlertIOS, ImagePickerIOS, TabBarIOS_. Furthermore, we can write Native modules for our Platform, but that is topic for itself.

Honorary mention goes to component parameters. Some components have Platform specific parameters which we will cover as we mention each component or set of components.

### Conclusion

To Platform or not to Platform, that is the difficult question. Usage of the platform-specific code is quite simple when it comes to React Native. As we have seen we have the variety of the choices. Either to create a platform-specific component or to make modification in component by determining OS. So it is all up to us, and our case scenario.

The code used in this article can be found at :

[nedimb86/RNPlatform](https://github.com/nedimb86/RNPlatform)

* * *