As I wrote a mobile app in react-native

my name is Alexey Androsov, I have been working in Yandex frontend developer. Two years ago me and my partners came up with the idea to create a mobile social network Verb. The idea of a Verb that users can share small status — “willows” — about what they are doing at this moment, the simple things that I want to tell my friends, but nowhere to write about it. And we even got investment, but now not about it. Today I want to talk about how and why I wrote the mobile app in react-native.

I have a background in backend developer for more than 10 years of experience in web development, but creating a mobile application for me was a completely new area. What to do in this situation? Quickly learn Objective-C or Swift for iOS and Java for Android? In parallel to write two apps at once seemed a bad idea, one I clearly would not have been able to quickly implement all the ideas on the two platforms. So I started to look for options for cross-platform development.

Just in time came the hype around React, there was the react-native. Then I wanted to try it. Looking back, the choice to react-native fell, by and large, not because of some objective reasons, but rather because of the subjective; it was already PhoneGap (WebView using JavaScript, CSS, HTML), Xamarin (C#) and NativeScript (JavaScript, TypeScript, Angular).

Experience with PhoneGap I already had and use it didn't want to (was bribed native components instead of implementing them on web technologies), C# I didn't write in Angular is not wanted, so the choice fell on the RN.

As NativeScript, RN has binding native component in JS, a similar system of work (more on that later) and options.

The first version, with which we began, it became 0.7.1 (current version is 0.46), my first commit on 21 July 2015. The Android support was not there at all. She appeared only in September 2015 (0.11). In this case it was the “initial support” platform with a bunch of problems and flaws. It will take a lot of time before iOS and Android will be more or less equivalent in react-native.

I'll tell you that Android version we at some point decided to write in Java. The app is already needed, and the RN at the time was not ready (at the moment that problem anymore). But iOS version Once written entirely in react-native.

the

What is react native?


So, react-native is a framework for the development on the react cross-platform apps for iOS and Android. React is used here just as an idea but not the implementation: JSX component approach, state, props, life cycle components, CSS-in-JS.

If the analogy with the usual web development, here:

the
    the
  • no HTML, but there are native components in JSX (<View/> <Text/> <Image/>)
  • the
  • no CSS. All styles are written in CSS-in-JS, layout is based on polyfile for flexbox (it is a little different from standard, e.g. flex-direction default column, not row).
  • the
  • is not the usual DOM API. No window, document just like. Of the usual API only GeoLocation API (navigator.geolocation) and XHR

The layout component looks like this:

the
render() {
return (
<View style={ styles.container }>
<TouchableOpacity onPress={ this.props.onPress }>
<Image source={ require('../icons/close.png') } resizeMode="cover"/>
</TouchableOpacity>
<Text style={styles.placeText} numberOfLines={1}>
{ myText.join(', ') }
</Text>
<ScrollView
keyboardDismissMode="on-drag"
refreshControl={<RefreshControl/>}
/>
{this.props.children}
</ScrollView>
</View>
);
}

To make it easier to understand let me give an analogy with the usual HTML. <View/> — <div/> <Touchable*/> — <a/> (there are several, with different reactions to pressure) <Image/> — <img/> <ScrollView/> something like <div style=”overflow: scroll”/>

CSS looks more familiar:

the
const styles = StyleSheet.create({

fontSize: PixelRatio.getPixelSizeForLayoutSize(7),
color: 'rgba(0, 0, 0, 0.60)'
},

suggestUser: {
height: PixelRatio.getPixelSizeForLayoutSize(100),

backgroundColor: '#FFF',
shadowColor: '#000',
shadowOffset: {
height: -5
},
shadowRadius: 5,
shadowOpacity: 0.5
}
};

Compiles the StyleSheet declares and styles, they are directly passed to native, not to chase every time. PixelRatio need for a proportional increase in the size of the elements depending on the screen.

How does RN


If great article from Tadeu Zagallo about the colon RN, I will briefly describe its essence.

In iOS there are three thread

— shadow queue processing and rendering layout
— main thread — then work components
— JavaScript-thread — work here JS

The General scheme looks like this: JS is executed (in fact React), the result must be passed to native code. There is a special bridge that using JSON sends a set of instructions. RN executes them and renders the native platform components. The result of using the same bridge can return back to JS.

image

All communication is asynchronous. In this case the bottleneck is in the bridge, serializing and deserializing data. Out interesting features:

the
    the
  • to Send large bundles of data JS<->native is a bad idea, it may be slow
  • the
  • to Do the big action on JS is also a bad idea. It will be a great security threads and slow down the rendering, no 60fps will not work.
  • the
  • Make frequent actions (e.g., animation or onscreen control) to JS also does not work, will slow down.

Total, the General rule is: we must not forget that we are running with native code, not JS. All you can do native has to be native.

the

Write once, run everywhere?


There it was ). In fact, the paradigm is: learn once, write everywhere. Why is it so? All native, so forget completely cross-platform. Platforms are different, and therefore different native components. They have different logic and mechanics of interaction. This applies mainly to components of navigation and user interaction. Therefore, in early development it makes sense to just distribute the blank application with basic screens and transitions. Here the difference ends, all internal components are likely to be the same. Convenience adds itself RN, platformspecific the entire code can be divided into files component.ios.js and component.android.js then for each platform will gather their own version without the if inside.

the

the iOS version of the Verb from the inside


From within the app written in react-native + redux. Redux came in handy, by the way, not just as a good library to manage application state, but also for communication between components. RN provokes to write pure components, without side effects or use global objects, so communication of components via shared state is almost the only normal way.

Plugins:

the
    the
  • React-native-deprecated-custom-components — I use an old Navigator, because it has not moved to the new react-navigation due to loads of bugs
  • the
  • React-native-device-info — information about UUID, version, and locale of the device
  • the
  • React-native-fbsdk — bridge FBSDK
  • the
  • React-native-imagepicker — my own harness over ActionSheetIOS, CameraRoll and ImagePickerIOS to download gallery
  • the
  • React-native-l20n — localization with l20n
  • the
  • React-native-linear-gradient implementation of the gradient
  • the
  • React-native-pagecontrol — my binding in UIPageControl
  • the
  • React-native-photo-view — simple library to do full-screen photo gallery
  • the
  • React-native-svg — binding in svg
  • the
  • React-native-vkontakte-login — bridge VKSDK

Stats:

the
    the
  • react-native-fabric bridge at Fabric and Crashlytics
  • the
  • React-native-google-analytics bridge — a bridge in GA
  • the
  • React-native-sentry — collect crashes or send in your own installation Sentry
  • the
  • React-native-bugsnag — bridge BugSnag

In the collection of crashes are now the most important thing to get a stacktrace in JS. This Fabic is not able, Sentry is better, the best proved BugSnag. But we still decided to move to the Sentry that all the problems were in one place.
We also use geolocation and push. In react-native for.

The important part is the performance. As I wrote, the bottleneck in RN is the bridge JS<->native, so the issue of reducing the number of redraws becomes upright. It follows that all the advice and best practice from react and redux are very important. React.PureComponent shouldCompomentUpdate or less connect-components, flat data structures, immutability — all give good performance gains.

the

non-Obvious tips


It is not necessary to delay the update versions. Before, when RN was produced every 2 weeks and almost every version has had incompatible changes, this advice was of great value. For 1-2 months the framework could change very much, so to be updated once for a couple of version was very difficult. Now the situation is better, releases once a month, the framework does not change so much. But I as before updated as soon as new versions come out.

Unification react component (here need the help of a designer) allows you to quickly develop new screens. Generally, a component approach and quick binding component this is a good thing how react and react-native.

boilerplate for creating new screens in rn + redux is large enough. As in react+redux and rn+redux will have to write a lot of code to create a new screen: create a component screen, register it in the Navigator, write actions and reducer to move the screen. Plus standard boilerplate for processing data for a new screen.

It is not necessary to write all on JS. The application should write as close to the native, look for binding in the desired native components or write their own. I assure you, it is not difficult.

Need to participate in the community. In RN it is enough bugs and flaws, but there is no problem to improve. The maintainers are actively involved in PR. However, it is often necessary to fix bugs in the native code, so Java or Objective-C will have to brush up. All of my PR was accepted. For example, I fixed a few bugs in the camera, or uploading pictures to the server.

the

Conclusion


To write in react-native proved to be convenient, fast and pleasant. It really allows you to quickly prototype applications and bring them to release. The technology is young, so there are typical problems of early adopters (e.g., periodic incompatible changes). But with each release of the RN is getting better and more stable, Facebook has made this much effort and makes him a bet. To the current time of the Facebook application already written in react-native, and supports Android reached the level of iOS.

I've done enough with technology and I can say that to write is not too big iOS app, similar to Twitter or Instagram, quite real. Unfortunately, deeply to try android and did not work, so I can not argue, but I hope that in the future it will be possible to try to compete with our native iOS version.

And we are looking for a remote developer on a part time! Write on doochik@ya.ru.

the

Useful links


the
Article based on information from habrahabr.ru

Популярные сообщения из этого блога

Approval of WSUS updates: import, export, copy

The Hilbert curve vs. Z-order

Configuring a C++ project in Eclipse for example SFML application