React Native research report, reactnative

Source: Internet
Author: User

React Native research report, reactnative

Facebook opened up the React Native iOS framework in March, which made both mobile developers and web developers excited: mobile developers of native think a lot of estimation is Facebook's sentence: "learn once, write everywhere", and web developers are excited to estimate that, you don't need to learn iOS's unfamiliar OC or swift language. You can use your familiar javascript language to develop a native mobile APP. So whether the newly released react native can carry the expectations of developers in the two camps. My colleagues and I did some research on react native for a period of time and gradually got my own answer:

This article assumes that the reader is familiar with iOS APP development, but lacks the knowledge of web Front-end development (like myself). On this basis, the reader tries to clarify what react native is and how to use it; and whether it is worth using.

1. What is React Native?

First, what is react native? It is a set of open-source Facebook frameworks,The objective is to use JavaScript to compile iOS native controls.. To put it bluntly, you use the code written in JavaScript (the same below) to bridge to the standard iOS program written in Xcode through react-native lib. In JS programs, developers can use a set of react native defined classes that are equivalent to the UI control classes in cocoa touch to complete the development of the UI Layer, the Xcode compiler uses react-native lib to compile JS Code into the iOS native UI component. The view debugging function of Xcode shows the JS code compilation result, these JS languages are indeed compiled into UIView and other objects, rather than webview that is often used on H5 interfaces. With this understanding, we are no longer familiar with react native.

To sum up, you can think that react native is a framework that allows you to use Javascript instead of traditional Objective-C or Swift to write the interface logic of iOS apps (V layer in MVC Framework. Those who have used swift may even think that JS and swift have many similar syntaxes (well, the swift five kernels are well known). For example, defining a variable uses the keyword var. The biggest highlights of this framework are:

You can build a React Native development environment directly according to the instructions on the official website of Facebook. there is basically no pitfall and it can be completed very quickly.

In addition to the creation of the runtime environment, you also need to compile the JavaScript code environment. Xcode is not the best tool! There are many useful Javascript editors on the Internet, such as Sublime Text and atom.

3. React Native technology constitutes a basic element of 3.1

The React Native library contains both OC code and javascript code. These two types of Code provide a set of elements used to build the UI system, including but not limited:

  • OC traditional UI components;
  • OC-based Gesture Recognition and event response systems (such as TouchableHighlight );
  • Stream-based layout system;

    After reading the API documentation on the official Facebook website, we can find that it is basically the most common UI control on the Cocoa Touch framework:

Basically, writing code with JS also uses these basic components to build our UI. In addition, you can also customize your own modules in OC and use them in React Native through bridging.

3.2 Event Response System in React Native

The biggest difference between a local APP and a web Client is that the local APP has a perfect event response system, allowing users to enjoy a better user experience. React Native also provides a set of Event Response Systems, which trace the source code of React Native (in the ResponderEventPlugin. js file) to see the basic process of React native Event Response:

It can be seen that the response system of React native is similar to Cocoa touch. If a view wants to respond to an event, it only needs to implement the function:

  • View. props. onStartShouldSetResponder: (evt) => true,-do you want the current view to be the responder of touch?
  • View. props. onMoveShouldSetResponder: (evt) => true,-do you want the current view to be the responder of the move event?

If true is returned and the attempt is to become the first responder, one of the following two functions will be called:

  • View. props. onResponderGrant: (evt) =>{}-the current view is the first responder. The Interaction Effect of the response (such as the background color change) and other event-triggered logic are displayed here;
  • View. props. onResponderReject: (evt) =>{}-other views are the first responders;

    Considering the complexity of the response system, React Native implements some abstract classes Based on Event Response encapsulation, such as TouchbleHighlight of UIButton in Cocoa Touch, you can place the view in the area where you want the interaction effect. Let's take a look at how to use TouchbleHighlight:

3.3 React native UI update Logic

In the Cocoa Touch system, UI update is a typical MVC mode: the Controller updates the view layer display through data changes, but it is quite different in React Native: react Native uses the state machine mechanism to update the entire view layer. Before introducing this section, you have to first talk about the React Native rendering method:

From the code snippets given in the previous image, the reader can also find that the method for building this page is similar to the HTML language: the hierarchical page logic (parent-child relationship) is constructed through the tag system ), the layout code is controlled by separate code in CSS mode, which separates the business logic from the layout logic so that the entire code hierarchy logic is clearer.

In React Native, the entire UI is a component tree: the previously mentioned ListView and other UI components are a specific component. React Native compiles the component tree into a virtual-DOM: virtual Document Object Model. readers who are familiar with HTML may be very familiar with this DOM. That is, the DOM. The entire UI relationship can be clearly reflected through this virtual-DOM, more importantly, the UI update logic of React Native is also implemented based on this tree: we know that in general, a page is updated, it must be driven by data changes, such as network data updates or touch events caused by user touch (and follow-up of business logic ), so how can we bind the changes to the data with the interface refresh? How do I know which part of the UI needs to be refreshed after the data is changed? You must know that re-drawing the entire interface for each data update is really a thankless thing: not only is your APP in a high-load running state, but your user experience is also poor. React Native cleverly maintains a state machine through the state variable provided by the user, and uses this state machine to drive the UI update of the virtual DOM tree, as shown in:

After the state information is designed, React Native calculates the DOM component based on the Code logic and needs to be updated. Developers do not need to intervene actively throughout the process, developers only need to establish a state system and maintain state information based on data changes. React Native will do all this for you in the background.

So what is the state in a component? It is actually an attribute, such as a bool value or array or any type supported by other JS. A component object actually contains two types of attributes: property and state. The former is mainly a fixed value attribute, and the latter is the data that will change, this change will lead to some re-painting properties on the interface, such as the data source on the list page. How to distinguish whether an attribute should be classified as property or state? Facebook's React official website documents: think in react has a detailed introduction, so I will not go into details here.

3.4 React Native Communication Mechanism

Before talking about specific communication principles, Let's first look at the code implementation. The communication here refers to whether the modules written in javascript and the local modules written in OC can directly call each other, as shown in:

Before going into the details, let's take a look at the simple situation of a class object directly calling another class object in pure OC code. What the main call module must know is:

We can regard the modules written by JS Code in React Native and the local modules written by OC as two unfamiliar cities. Obviously, to communicate effectively between the two cities, they must have a map of the other city. In the React Native world, the two maps are the module configuration table, which looks like a purple drop (some of the information is from the Bang's blog ):

Since the communication between the two parties can be solved through the module configuration table, now the problem is simplified to: how to provide this table to the compilation and runtime systems for further analysis, we will discuss the two parts of the communication atmosphere: The JS module calls the OC local module and the OC local module calls the JS module:

3.4.1 The JS module calls the OC local module

An OC module is a common class written by OC. By default, it cannot be captured by the Javascript runtime system and called, it must provide or register itself to the compilation and runtime systems, and expose the attributes that you want to expose and the methods that can be called. The trick is:

// CalendarManager.h#import "RCTBridgeModule.h"@interface CalendarManager : NSObject <RCTBridgeModule>@end
// CalendarManager.m@implementation CalendarManagerRCT_EXPORT_MODULE();......RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location){  RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);}@end

The calling method in the main module JS is as follows:

var CalendarManager = require('NativeModules').CalendarManager;CalendarManager.addEvent('Birthday Party', '4 Privet Drive, Surrey');

The exposed method supports the following parameter types:

  • String (NSString)
  • Number (NSInteger, float, double, CGFloat, NSNumber)
  • Boolean (BOOL, NSNumber)
  • Array (NSArray) of any types from this list
  • Map (NSDictionary) with string keys and values of any type from this list
  • Function (RCTResponseSenderBlock)

That's right! That's easy! Awesome, isn' t it? Pai_^

In addition, for parameters that the OC module wants to expose to the JS module, you can useconstantsToExportProvided by the method, this method returns a dictionary, the sample code is as follows:
In OC module:

- (NSDictionary *)constantsToExport{  return @{ @"firstDayOfTheWeek": @"Monday" };}

You can directly obtain the parameters returned by the function in the JS module:

console.log(CalendarManager.firstDayOfTheWeek);
3.4.2 The OC local module calls the JS Module

To call methods in the JS module, the local Class Object of OB must also follow the method mentioned in 3.4.1.RCTBridgeModelIn addition to the above OC modules, the module configuration table created by the compilerremoteModulesBesides, the JS module is also saved.localModules.RCTBridgeModelThe Protocol providesRCTBridgeAttribute object. This object provides a method to access the JS module. The Code is as follows:

/** * This method is used to call functions in the JavaScript application context. * It is primarily intended for use by modules that require two-way communication * with the JavaScript code.  */- (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args;

In addition to this direct call method, the official FacebookFacebook React Native website also provides a method to indirectly implement JS module calls, that is, throughRCTEventDispatcherTo send and receive messages. The diagram is as follows:

The specific implementation code is as follows:

First, send a notification in the local OC codeEventReminder:

#import "RCTBridge.h"#import "RCTEventDispatcher.h"@implementation CalendarManager@synthesize bridge = _bridge;- (void)calendarEventReminderReceived:(NSNotification *)notification{  NSString *eventName = notification.userInfo[@"name"];  [self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder"                                               body:@{@"name": eventName}];}@end

Second, listen in the JS ModuleEventReminderNotification, and add the corresponding notification response function:

var subscription = DeviceEventEmitter.addListener(  'EventReminder',  (reminder) => console.log(reminder.name));...// Don't forget to unsubscribe, typically in componentWillUnmountsubscription.remove();

By receiving and sending notifications, the coupling between OC and JS modules can be reduced.RCTBridgeYou can viewRCTEventDispatcherInsendDeviceEventWithNameSource code implementation can be found:

- (void)sendDeviceEventWithName:(NSString *)name body:(id)body{  [_bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit"                    args:body ? @[name, body] : @[name]];}

To sum up, we can think that the communication mode of the OC module directly calls the JS module mainly throughRCTBridgeModelProtocolRCTBridgeOfsendDeviceEventWithNameIn addition to calling this method directly, you can also call this method indirectly using the notification method (only the notification method is described on the official FacebookFacebook React Native website, it may be obvious that this is the method recommended by Facebook. For specific use, developers must act cheaply based on the situation ).

3.4.3 React Native communication mechanism Summary

Through the above two code demonstrations, we can quickly implement dual-channel communication between the OC module and the JS module. Basically, whether it is OC-based JS or JS-based OC, the core of its dependency is the module configuration table (remote and local) provided by the bilateral modules. For details about its implementation principles, refer to the Bang's blog.

3.5. React Native UI layout Mechanism

Whether it is a web page or a local Native PAGE, UI layout is an important part in development. Compatibility with pages and devices of multiple sizes is the primary issue facing developers. With the increasingly diverse iPhone screen sizes (at least iphone4s/5S/6/6 plus four sizes ), apple is increasingly focusing on autolayout, which is a typical relative layout method. developers can add constraints to the UI components by visually editing the xib or storyboard environment, during runtime, the system uses the Automatic Layout Engine to calculate the Frame information of each control in the UI based on the actual screen size, so as to achieve the UI layout.

Unlike Cocoa Touch, React Native adopts a completely different system in UI layout: html css, which is also the streaming layout of mainstream web pages, developers can write each layout information into a separate style table to analyze the layout and business logic. developers can complete the layout information using html css syntax:

var styles = StyleSheet.create({  scrollView: {    backgroundColor: '#6A85B1',    height: 300,  },  button: {    margin: 7,    padding: 5,    alignItems: 'center',    backgroundColor: '#eaeaea',    borderRadius: 3,  },  buttonContents: {    flexDirection: 'row',    width: 64,    height: 64,  },  img: {    width: 64,    height: 64,  }});

In addition to the standard html css Layout, React Native also supports the Layout of the Flexbox module. According to the instructions on its official website, the Flexbox Layout module aims to provide a more efficient Layout, dynamically determines the size, center, interval, or even size of the sub-item in a iner.

FlexBox layout objects have only two types: container and item, as shown in:

There are six or seven layout attribute keywords for containers and sub-items respectively, as shown below:

Attributes applied to Container: display flex-direction flex-wrap flex-flow // = flex-direction + flex-wrap justify-content align-items align-content attributes applied to items: order flex-grow flex-shrink flex-basis flex // = flex-grow + flex-shrink + flex-basis align-self

To use FlexBox in CSS, you only need to directly add the corresponding keywords, as shown in the following code. The significance of each layout keyword can be obtained through this article:

.flex-container {  /* We first create a flex layout context */  display: flex;  /* Then we define the flow direction and if we allow the items to wrap    * Remember this is the same as:   * flex-direction: row;   * flex-wrap: wrap;   */  flex-flow: row wrap;  /* Then we define how is distributed the remaining space */  justify-content: space-around;}

The layout of html css Style is more dynamic than the Automatic Layout of iOS, but it can only be written in pure code mode, which is really a bit painful, moreover, for the majority of iOS Mobile ape who do not have web Front-end development experience, CSS la s are still a bit unfamiliar: basically, you need to change the way of thinking before you can clearly consider the specific layout details, and for more complex dynamic scenarios, this layout method may be more difficult to implement and maintain.

4. Is React Native available now?

While React Native is booming, we should carefully discuss whether the time to use React Native is ripe. During the investigation, we found several points worth noting:

4.1 Data Interaction Between the JS module and the OC module can only be transmitted through a dictionary

The dictionary is a loose data structure in the OC module. If React Native is used to draw the UI interface, the OC module is responsible for data processing, then the interaction between the two can only be a dictionary. Model class objects defined by OC (for example, model Objects Created when core data is used) cannot be directly transmitted to the JS module, and must be converted into dictionaries in advance, this undoubtedly adds an additional layer of processing logic, which is bound to bring some potential risks.

Taking using CoreData for data storage as an example, the interaction between the entire data layer is like this:

This restriction can only be passed through the dictionary, so we cannot directly use the data objects in the OC module as the state attribute driving page updates in the JS module. We will have to add an intermediate layer to convert the data. This change has been mapped to the JS module to drive the UI Layer update.

4.2 learn once of React Native, the implementation of write everywhere is still available

When pushing React Native, Facebook stressed that its biggest features are: Learn once, write where. however, the actual situation is that React Native Android is expected to be released in October 2015, which is also a risk for users who want the three-end (Web/iOS/Android) architecture to be consistent. In addition, let's take a closer look at the React Native iOS framework. There are many modules that are closely coupled with the iOS local module. For example, some components ending with iOS are only available in iOS, and the code of these modules is used, in the future, it may be impossible to directly run on Android, So React Native has a lot to do from the real cross-platform:

**COMPONENTS**ActivityIndicatorIOSDatePickerIOSImageListViewMapViewNavigatorNavigatorIOSPickerIOSScrollViewSliderIOSSwitchIOSTabBarIOSTabBarIOS.Item
4.3 problems with Listview performance in React Native

There is an issue in React Native on github that is particularly worrying: ListView renders all rows? Several of the comments reveal the fact that the React Native ListView may render all the rows (cells) at one time ):

@ide I'm a noob at instruments profiler... So here's brief summary from me taking a look at it.cpu profile looks like most of the time is spent here (recursing through subviews), in RCTView.m :- (void)react_updateClippedSubviewsWithClipRect:(CGRect)clipRect relativeToView:(UIView *)clipViewIn memory profile major causes of persisted memory (645 MB total) are:VM: CG Graphics Data (410 MB)VM: CoreAnimation (141 MB)VM: JS Garbage Collector (61 MB)...Unmount the ListView component, and total persisted memory drops to 74 MB total:VM: JS Garbage Collector 58 MBVM: CoreUI image data...
Kureev commented 24 days agoIt's totally insane: my iPhone 5c crashes after 700 list items. If I'm going to write a chat - it's blocking for me.Also I got a lot of "Cannot find single active touch"
samfriend commented 14 days agomy < ListView pagingEnabled={true} onEndReached={this.loadAnotherFiftyArticles} >50 rows/pages of < Image / > < Title/ > < Description/ >3rd Load append (total 150)Received memory warningReceived memory warningReceived memory warningCrash Physical iPhone 6 PlusAlso I got a lot of "Cannot find single active touch" time to time

To prove the concerns of netizens, we use Xcode's view perspective tool to check the Demo on the React Native Official Website: The ListView of UIExplorer to see if all the rows are re-painted at a time, the Demo running interface is displayed:

Then we used Xcode's Debug View Hierarchy to View the interface Hierarchy of the attempt. The result surprised us: it actually drew all the rows!

Let's look at the situation of scrollView again. Well, I am not good at it after reading it:

If this is the case, it is enough to give up using React Native, at least temporarily!

4.4 unsatisfactory UI Layout System of React Native

We know that the web Front-end html css used by React Native is also a stream layout. The entire UI is built through a tree structure, and the layout is also based on this, and needs to be created manually. Compared to children's shoes that use autolayout layout on iOS, they must be deeply stabbed by this non-visual layout method: you must transform all the UI display effects into complicated layout constraints in your mind.


The autolayout visual layout is the most lacking in React Native

Another disadvantage of CSS layout is that, compared with the traditional Native layout method, accuracy control is not very good, and the final layout effect may be far from the original intention of the designer. In autolayout, we can use sizeclass to customize the layout of the horizontal and vertical screens. However, this method cannot be implemented using CSS currently.

4.4 conclusion

Through appeal analysis, we found that React Native still has many shortcomings in terms of performance and development convenience. Currently, it has not implemented the goal of "Learn Once, Write Everywhere", but it has many problems, the performance of a single ListView is the biggest bottleneck. React Native is still in its initial exploration phase. How will it develop in the next phase depends on the next action of its old-fashioned Facebook. Therefore, I suggest that you do not use React Native Technology in existing development projects to keep up with the technology.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.