React Native is a hybrid mobile application development framework in Dissecting React Native with some understanding of my own development

React Native is one of the most popular cross-platform mobile application development frameworks. This article provides an overview of React Native and the authors’ best practices for developing React Native applications.

When developing mobile applications, we can choose to use native, purely Web-based, or use a hybrid approach (that is, using a combination of native and Web-based technologies). Cross-platform hybrid applications of HTML, CSS, and JavaScript can be written using open source platforms such as Apache Cordova (or Adobe PhoneGap). These applications run in a native Web view (browser), so they look like Web applications, but native functions and apis can be invoked using JavaScript and some Apache Cordova plug-ins. So you can use a user interface that looks more like a Web app than a native app to get an app to the Apple Store or Google Play. Alternatively, you can write native applications using Xamarin in C#, XAML, and CSS. For non-native Mobile Web applications written in HTML5, CSS and JavaScript, frameworks such as jQuery Mobile can also be used.

React Native takes a different approach to hybrid mobile app development. React, React Native uses JavaScript to build web-based interactive interfaces instead of generating Native UI components. As a result, it provides richer UI experience and can invoke UI of the underlying framework. React Native has become a popular mobile development technology, providing a powerful framework for building Native cross-platform mobile applications using JavaScript, or writing Native code in Objective-C, Swift, or Java to bridge when needed.

React Native has pros and cons. On the positive side, React Native has become popular with the supported open source community for building mobile apps for iOS and Android using a set of technologies such as JSX, the React Native component and JavaScript. This, in turn, helps keep iOS and Android apps in sync when new versions are released. However, React Native is still evolving, and it can be confusing when deciding which libraries to use when you don’t currently need features that React Native provides, such as how to navigate UI or use maps. In addition, depending on the complexity of your application, you may need to write platform-independent code to address mobile platform differences. For complex applications, it may be necessary to write custom components or in-depth knowledge of iOS and Android (for example, UI components needed for performance reasons or not supported when adding React Native to an existing Native application).

Configure the React Native environment

React Native’s core language is JavaScript, specifically ECMAScript 6 (ES6). Therefore, familiarize yourself with some of the latest ES6 features. In addition, before you start developing your first React Native application, you need to install the necessary tools, such as the IDE, JavaScript libraries, and so on. In addition, you need to understand the core React Native API.

ECMAScript function of 6

ES6 introduces a number of improvements, some of which are worth mentioning because they are already used in the latest React Native framework:

  • Variables and scope: The keywords var, let, and const represent variable scope, where var is function scope, let is block scope, and const is block scope. A const variable is a constant, but in JavaScript it is mutable for objects and arrays. The interpreter promotes or moves variable declarations to the top of the scope of var declarations, while let and const declarations are not suspended.
  • Arrow function: A new type of function that allows for a more compact, concise representation, and has static or lexical definitions (it does not revolve around it lexically). Take a look at these examples.

Arrow functions with no specified arguments:

() => { ... }
Copy the code

Take one argument, note the omitted parentheses:

x => { ... }
Copy the code

Specify several parameters:

(x, y) => {* 
...
}
Copy the code

The arrow of the parameter definition and arrow function must be on the same line.

  • Promises: Promises is an alternative API to asynchronous programming that offers advantages over traditional callbacks such as linking and parallel execution.
  function myAsyncFunc() {
    return new Promise(
    function (resolve, reject) {
          :
    resolve(result);
           :
           if(error) { reject(error); }}); }Copy the code

Compare the previous asynchronous functions:

MyAsyncFunc (). Then (result = \ > {...}). The catch (error = \ > {...});Copy the code

This is just one example of the new features, but there are many others. A good online reference for Exploring ES6 is Axel Rauschmayer’s Exploring ES6.

Next, let’s look at how to set up the development platform and environment.

Set up environment and engineering

Currently, iOS native apps can only be developed on macOS. Since most mobile apps run on both Android and iOS, you should consider developing React Native for Mac.

Before you can create a project, you need to install a bunch of things, mainly including:

  • Android Studio and Xcode tools: Install the latest version to build and publish the application. For Android development, make sure you configure the emulator correctly for the version of the Android API you want to run.

  • JavaScript IDE or text editor: You don’t need Xcode or Android Studio to write JavaScript code, all you really need is a text editor. Using Atom (developed by GitHub), Sublime Text, or whatever good Text editor you like, I’m currently using VSC.

  • JavaScript or React Native Package: Install several tools to manage the React Native package and tripartite libraries, including:

    • Download Node.js from nodejs.org: In order for the JavaScript runtime to allow access to NPM, this is a handy tool created by the Node.js project for managing open source packages. Be sure to download the latest LTS (long Term support) version of Node.js. Also included in this download is a development server called Metro Bundler, which provides real-time updated rendering during debugging.
    • Download create-React-native app: Use this tool to start development. It can create a base project. Use NPM to download:

    sudo npm install -g create-react-native-app

    • Download common third-party libraries. React Nativ provides many basic components that are simpler to use than the native API. Regular use of mobile applications may include cameras, management status, and navigation, maps, ICONS, and checkboxes. All of these are available from the React Native community:

      • react-native-navigation
      • react-native-vector-icons
      • redux
      • React-native-maps

      In addition, you can go to React Native Elements for additional UI component Elements you need. The UI components mentioned above are needed to develop a fully functional app. Install previous packages using this method:

      npm install _package-name_ --save

    • React Native Debugger: The React Native Debugger is a great Debugger and a standalone app that includes React Inspector and Redux DevTools. After configuring the environment, you can connect it to the application (note: only one application can be adjusted at a time). You can easily check the status of the React Native application in real time.

Now let’s set up a simple application and run it:

1. Create a project. To create a project, specify the project path to be created. By default, the project path will be created in the current path:

create-react-native-app [APPNAME]

cd [APPNAME]

Copy the code

Note: This step creates a React Native app template with no configuration. Read more about create-React-Native App in the GitHub project.

Once installed, you can use NPM to run the application by executing the following commands:

  • npm startRun the app
  • npm run ios: Similar to NPM start, this is used to run iOS apps
  • npm run android: Run the Android application. If you need to run the emulator, you need to open the emulator in advance
  • npm run eject: Pop the app from the current create-React-Native mode so you have complete control over the app build process (which I didn’t use)

2. Start the app. Run the application on the emulator by running NPM Run Android and NPM Run ios. This will launch the application in development mode. It also launches Metro Bundler, which updates the app in real time after code changes (great for debugging mobile apps).

If the operation succeeds, the following message is displayed:

React Native API Overview

Let’s take a quick look at the React Native API, the React Native transition, which inherits the concepts of JSX, State, props, and component lifecycle. It then extends React by providing support for native UI components and functionality. This is done by importing React and React Native functionality, as shown in Listing 1:

Listing 1. Import from React and React Native

import React, { Component } from **'react'**

import { View, ScrollView, StyleSheet } from **'react-native**'


Copy the code

Once imported, we can access React Native’s corresponding components, which support many of the common UI components we need:

  • Basic UI components: View, Text, Image, TextInput, ScrollView, and StyleSheet. In addition, UI controls such as Button, Picker, Slider, and Switch are provided.
  • Lists: Lists of FlatList (used to render scrollable lists) and SectionList (similar to FlatList but used for segmented lists)
  • Android specific components: such as Android BackHandler, DatePickerAndroid, ToastAndroid.
  • Ios-specific components: AlertIOS, ImagePickerIOS, NavitatorIOS, TabBarIOS.
  • Common Components: You can query all common Components on Components and APIs.

It’s also important to note that React Native offers a lot of functionality that wasn’t originally supported. Use maps, even ICONS and check boxes. Although the underlying operating system supports React Native, it still requires third-party libraries to be installed. That said, anything complex or unsupported that React Native (including development tools) supports requires us to write additional code or use third-party libraries to host it.

Use React Native to build applications

A regular React Native application consists of a number of components, as shown here:

In an application container, each interface may contain one or more Views (and styles), interface jump navigation, state management, and data models. There is also local storage and network request capabilities. Last but not least, there are many third-party libraries that can extend the functionality of an application.

Here are some of the figures:

Screens: Views and styles

The application container contains a collection of Screens and other components. The application itself consists of a number of screens, each containing multiple views, such as buttons, text input, and lists. The View is the most basic component for building a user interface, and maps to the native View component for iOS and Android.

Listing 2 is an example interface that contains a list, implemented using ScrollView, and a list of tasks encapsulated in the Checkbox UI component:

# components/TaskList/TaskList.js

import React, { Component } from 'react'
import { View, ScrollView, StyleSheet } from 'react-native'
import { CheckBox } from 'react-native-elements'

import styles from './TaskListStyle; export default class TaskList extends Component { renderTaskItem = (item, idx) => { return ( 
       
       
         onPressItem(item, idx) } /> 
       
       ); } render() { const {list} = this.props return ( 
      
        {list.map( this.renderTaskItem )} 
       ) } }Copy the code

The list component in the code requires importing various dependencies, including a third-party Checkbox UI component not found in React Native, which can be downloaded from React Native Elements.

In Listing 2, UI components and styles are separate. We can create more advanced UI components and isolate them from styles. We put all the components in a subdirectory, each with its component.js and style.js files, as shown in Listing 3:

./Components
+-TaskList
  +-TaskList.js
  +-TaskListStyle.js
Copy the code

Or, use a more general approach:

+-TaskList
  +-index.js
  +-style.js
Copy the code

Listing 4 shows an example of a style file:

# components/TaskList/TaskListStyle.js

import { StyleSheet } from 'react-native';

// Define the styles
export default StyleSheet.create({
    container: {
        flex: 1,
        paddingLeft: 20,
      },

      row: {
        flex: 1,
        flexDirection: 'row',
        alignItems: 'flex-start',}});Copy the code

Styles need to be created using the StyleSheet component, which is similar to a CSS StyleSheet. See the Individual UI Component for more variety of properties.

Adaptive layout

React Native provides a Dimensions component to detect screen sizes:

import { Dimensions } from 'react-native';
var {height, width} = Dimensions.get('window');
Copy the code

Dimensions can adjust the interface UI in real time according to needs; For example, we can adjust the UI as orientation changes, including changing the position and length of text input fields in landscape and portrait orientation, depending on the desired application style.

There’s another case where we might need to deal with UI adaptation. Such as the need to implement Androi D or ios-specific behavior. This includes differences related to both systems, such as the presentation and use of UI controls. To solve this design problem, we need to use different logic or styles or, in more complex cases, implement custom components. React Native therefore provides different ways to detect the system so that you can programmatically determine what actions to perform: using Platform components or even using platform-specific file extensions.

If Platform components are used to check the system, ios or Android is returned. Such as:

import {Platform} from 'react-native';


if (Platform.OS === 'ios') {}if (Platform.OS === 'android') {}Copy the code

Platform Also provides platform. select and platform. Version, which are used to check the Platform and Platform Version respectively. Refer to the platform documentation for more information. You should only use platform. OS and platform. select for minor changes. Otherwise, we would use a lot of hard-coded if or switch statements, which would make writing code harder to follow.

If you are writing more complex code or components, you should use a platform-specific file extension. In this approach, the code is split using each platform file. That is, if our code isn’t cross-platform, like our task list, we’ll write two files, one for iOS and one for Android, and let React Native select the corresponding file:

./Components
+-TaskList
  +-TaskList.io.js
  +-TaskList.android.js
  +-TaskListStyle.ios.js
  +-TaskListStyle.android.js
Copy the code

Then, tell React Native to select the correct file:

const TaskList = require('./Components/TaskList/TaskList);
Copy the code

This article doesn’t cover exactly what the differences are between iOS and Android, but considerations include rendering and using layouts for regular components or UI controls. Now, if it turns out that the layout design of Android and iOS apps differs in major ways, we can control the main app using index.ios.js and index.android.js files, respectively, instead of index.js. This gives you complete control over the application layout and flow across different platforms. To minimize duplicate code, it needs to be repackaged as a reusable program.

navigation

Navigation in React Native is a challenging area, as the navigation provided by React Native is either underpowered or ios-only. Instead, there are plenty of community projects that attempt to address cross-platform navigation, some more popular than others. React Native Navigation.

React Native Navigation provides a complete SET of apis for registering UI components, including apps with tabs, and launching individual UI apps. It also provides additional apis for managing modal and navigational jumps, as well as low-level apis for handling stacks, handling buttons, visibility, and customizing the navigator itself.

Install the latest stable version of React-Native Navigation (run NPM install React-Native Navigation –save) and follow the Android and iOS installation instructions on its website

In addition, a Navigator with a unique name must be registered with all Screen components by calling registerComponent (). Once registered, you can run either a Tab containing application or a single Screen application, as shown in Listing 8:

import { Navigation } from "react-native-navigation";
import MainScreen from "./src/screens/MainScreen/MainScreen";
:

// register the MainScreen component
Navigation.registerComponent(
  'MainScreen', () = >'MainScreen'
);

:
:

// Start the (single screen)App
export default () => Navigation.startSingleScreenApp({
  screen: {
    screen: "MainScreen",
    title: "Main Screen"}});Copy the code

If tab-based use is used, more screens need to be created because different tabs and their associated screens, TAB details, and styles must be specified, for example:

// Start the (tab-based) App
export default () => Navigation.startTabBasedApp({
    tabs: [
        {
            screen: "screen unique name",
            label: "label",
            title: "title",
            icon: icons[0],
            navigatorButtons: {
                leftButtons: [
                    {
                        icon: icons[2],
                        title: "title",
                        id: "unique id"
                    }
                ]
            }
        },
        {
            screen: "screen unique name",
            label: "label",
            title: "title",
            icon: icons[1],
            navigatorButtons: {
                leftButtons: [
                    {
                        icon: icons[2],
                        title: "title",
                        id: "unique id"
                    }
                ]
            }
        }
    ],
    tabsStyle: {
        tabBarSelectedButtonColor: "black"
    },
    drawer: {
        left: {
            screen: "drawer screen unique name"
        }
    },
    appStyle: {
        tabBarSelectedButtonColor: "red"}});Copy the code

You can switch between single and tab-based screens as needed by calling the corresponding functions. Also, notice the use of drawers in the previous example. Drawer side menus can be defined for individual Screen applications and tab-based applications.

The state administration

In React (and React Native), props and state are used to control components. Props (Properties) are parameters used to customize the component when it is created. For example, the Button component provides support for many properties; In Listing 10, title and onPress are props.

<Button
  onPress={onPressHandler}
  title="Learn More"/ > :Copy the code

Properties are set by React itself (by the parent component) and remain fixed throughout the life of the component. State is special data within the application that can be changed as needed to drive component behavior, such as refreshing data. State should be initialized in the constructor and can only be changed by calling setState. Listing 11 shows the use of state:

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {isActive: true};
  }

  toggleActiveState() {
      this.setState(previousState => {
          return{ isActive: ! previousState.isActive }; }); }render() {:}}Copy the code

Listing 11 is an example of simple state management, but if your application is more complex with many Screen components and intercomponent state management, you should leverage Redux. Redux is a more advanced approach to state management that provides a framework for implementing state management and related operations and handlers. But using Redux increases the complexity of your application, so you should consider using it only when you really need it (that is, for large, complex applications).

Persistent storage

React Native supports persistent storage with AsyncStorage. AsyncStorage is an easy-to-use asynchronous (persistent) key-value storage system that is global to the entire application. It’s easy because it doesn’t require too much setup. On iOS, it appears as a series of dictionaries or files. On Android, it is based on SQLite or RocksDB:

import {AsyncStorage} from 'react-native'
:

const USERNAMES_KEY = 'Usernames'

const user = {
    name: 'John',
    last: 'Smith',
    username: 'jsmith'
}

// Storing the item
AsyncStorage.setItem(USERNAMES_KEY, JSON.stringify(user))

:

// Get item promise to retrieve the item
AsyncStorage.getItem(USERNAMES_KEY).then((item) => {
    const userItem = JSON.parse(item)
})

:
Copy the code

However AsyncStorage has many limitations, such as low performance, no index, and no encryption. Let me say that again: it is not encrypted. If you want to store a lot of data, and performance and encryption are important to your application, consider alternatives such as Realm React Native. Realm React Native is cross-platform, performs better, supports encryption, and even comes with a version of ListView (with the same API signature as React Native ListView) optimized on top of Realm, Greatly improved access to local storage. Realm uses the static Schema approach to improve performance. Use the React-native database Realm in a react-native context.

class Usernames {
    static schema = {
        name: 'User',
        properties: {
            name: 'string',
            last: 'string',
            username: 'string',}}}let realm = new Realm({schema: [Usernames]});

realm.write(() => {
    realm.create('Usernames', { name: 'John', last: "Smit", username : "jsmith" });
});
Copy the code

network

Mobile applications are usually applications that require an Internet connection. Mobile applications connect to the network for authentication. React Native provides different network apis:

  • The original Ajax (asynchronous JavaScript + XML) XMLHttpRequest API
  • WebSockets, which provide full-duplex communication channels over TCP connections, also known as bidirectional equal dialogue
  • The Fetch API, the latest addition to the series, is similar to XMLHttpRequest, but with additional functionality.

Listing 14 Json files that fetch user data from the server using the FETCH API:

{
  "users": [{"name": "John Smith"."username": "jsmith"},
    { "name": "Matt People"."username": "mpeople"},
    { "name": "Graciela Lopez"."username": "glopez"},
    { "name": "Jeff Bezos"."username": "jbezos"},
  ]
}

--

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

export default class FetchUsernames extends React.Component {

  constructor(props){
    super(props);
  }

  // dispatch the fetch once the component mounts
  componentDidMount() {return fetch('https://... ')
      .then((response) => response.json())
      .then((responseJson) => {
this.setState({
          dataSource: responseJson.users,
        }, function(){
        });
      })
      .catch((error) => {
        console.error(error);
      });
  }

  // render the component, populating the FlatList from the 
  // state.dataSource that was in turn populated from the JSON
  render() {return( <View> <FlatList data={this.state.dataSource} renderItem={({item}) => <Text>{item.name}, {item.username}</Text>} keyExtractor={(item, index) => index} /> </View> ); }}Copy the code

Some notes about the FETCH API and network:

  • Notice the use of Promise in Listing 14. Fetch does not fail (reject) even if the response is HTTP 404 or 500. In other words, it will only reject network failures. To detect a non-network fault, check whether the status is returned normally.
  • By default, iOS blocks requests that are not encrypted using SSL. The only way to solve this problem is to add App Transport Security.
  • You can use NetInfo to detect or retrieve network information. It can detect network status, connection type (Wi-Fi, cellular) and active connection type (2G, 3G and 4G), but there are some differences between the two ends.

conclusion

This article only provides a high-level view of React Native. React Native is a complicated topic. If you want to dig deeper, you’ll need to examine each of the areas covered in this article in more detail.

React Native is a vibrant and growing framework and community. But React Native isn’t as mature as Native app development. It’s important to maintain a stable environment for Android, iOS, and React Native development, including all related development tools. For components that don’t exist in React Native, Google search and you’ll find the content you need. Keep in mind that the selected third-party library may change or maintenance may stop or be abandoned, which is a major risk to consider.

React Native isn’t for everyone or every project. This requires considering the time, effort, and cost of creating and maintaining React Native code, tools, development environments, and skill sets, rather than just focusing on Native code. Last year there were examples of large development organizations, such as Airbnb, that put a lot of effort and investment into React Native, but decided to go back to pure Native development.

The authors introduce

  • Wei Yuxiang: iOS development engineer of Guangzhou Reed APP Team

Push the information

  • We are recruiting partners, interested partners can send your resume to [email protected], note: from the nuggets community
  • For details, please click here –> Guangzhou Reed Information Technology