Create native UI component in React Native

Last Tuesday, I presented a live coding session at the ReactJS meetup in Paris hosted by Deezer about creating UI components based on native ones in React Native.

For the quick version, have a look at the slides:

First of all, there are a lot of misunderstanding about React Native architecture. Here is a schema to help you understand it:

Simplified schema of React Native architecture

To make it simple, there are three threads which are doing the whole job:

  • Shadow thread that will calculate the sizes and positions for all your UI elements
  • JS thread (instance of JavaScriptCore) that will execute your React code and returns a dictionary of the elements to be drawn
  • Main thread (in Objective-C) will take combine the return of the two previous threads and draw the elements at their right place

Now let’s get started by implementing a MapBox (mapping platform based on OpenStreetMap) component. I assume you just created a React Native project by following the instructions here.

A native UI component is divided in two parts:

  • Component view return a view (obviously) that will be drawn by the main thread and send the events to your JS thread through the bridge created by React
  • Component manager instantiates the component view with its dimensions and a reference to the bridge (if needed)

You need to download the iOS SDK of MapBox, drag’n’drop inside your XCode project and add as a embedded framework in your build settings.

Select your project on the left sidebar and select Build Settings in the project tabs

As of today, MapBox supports iOS 8+ for its dynamic framework (default one), so be sure to select the right deployment target.

Of course, the other options can be changed

Now let’s create a CocoaClass which is represented by two files (header + code)

// MapBoxManager.h
#import “RCTViewManager.h”
@interface MapBoxManager : RCTViewManager
@end
// MapBoxManager.m
#import “MapBoxManager.h”
#import “MapBoxView.h”
@implementation MapBoxManager
RCT_EXPORT_MODULE()
- (UIView *)view
{
return [[MapBoxView alloc] init];
}
@end

Notice the error that XCode shows saying MapBoxView.h doesn’t exist. No problem, we’re just about to create the component view that will create a MapBox instance: MapBoxView

// MapBoxView.h
#import “RCTView.h”
@interface MapBoxView : RCTView
@end
// MapBoxView.m
#import “MapBoxView.h”
@import Mapbox;
@implementation MapBoxView {
MGLMapView *_map;
}
- (instancetype)init
{
  self = [super init];
_map = [[MGLMapView alloc] initWithFrame:self.bounds];
_map.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

[self addSubview:_map];
return self;
}
@end

We need to link that view to an actual React component

// MapBox.js
import { requireNativeComponent } from ‘react-native’;
// requireNativeComponent automatically resolves this to “MapBoxManager”
module.exports = requireNativeComponent(‘MapBox’, null);

MapBox requires to set the API key. We can do it in the code or as a project variables. I prefer the last one. So open your Info.plist file and add MGLMapboxAccessToken entry as a key and your API key as a value. You can find it here.

Finally, we update index.ios.js and add our new component

// index.ios.js
import React, {
AppRegistry,
Component,
StyleSheet,
View
} from ‘react-native’;
import MapBox from ‘./MapBox’
class MyApp extends Component {
render() {
return (
<View style={styles.container}>
<MapBox style={styles.map} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: ‘center’,
backgroundColor: ‘#F5FCFF’,
},
map: {
flex: 1,
}
});
AppRegistry.registerComponent(‘MyApp’, () => MyApp);

And you get a shiny fullscreen map on your device!

Notice that we didn’t have to set explicitly the dimensions of the map to get it fullscreen. The nice flexbox system that Facebook implemented in React Native takes care of that for all types of devices.

MapBox has already their SDK adapted for React Native, so no need to reimplement everything. The purpose was to understand how to create a UI component based on an external library. Check it here.

I hope you enjoyed the tutorial. I didn’t dive into the events system or the integration with Android which need entire tutorials themselves. If you’re interested about them, here is some links to bookmark: