» » How to develop your first app with React Native

How to develop your first app with React Native

I want to talk a little about what React Native is, why it is important and popular now, and together with you I will try to write a small project to demonstrate the basics.

What is React Native?



First you need to figure out what React is. React is a tool for creating user interfaces. Its main task is to provide a display on the screen of what can be seen on web pages. React makes it easy to create interfaces by dividing each page into small fragments and components. It is very convenient for creating web applications and does not require a large entry threshold. So, the guys from Facebook thought it would be cool if React could be used to create cross-platform mobile applications, and in 2015 React Native was presented to the public and appeared on GitHub, where everyone could already contribute. React is popular for several reasons. It is compact and has high performance, especially when working with rapidly changing data. Due to its component structure,

The world of cross-platform mobile development already had its own solutions, for example Apache Cordova, a technology that allowed using HTML + CSS + jаvascript + native functionality of the platform on which the application was launched to run it. However, the technology has a big problem - speed. There are also others at the moment, such as Xamarin, Flutter, QT, and so on.

In React Native, code is written in jаvascript and executed using jаvascriptCore, the engine that Safari uses. You can also use native platform modules, such as a camera or Bluetooth. For this, code is written that implements the functionality in a language that is intended for development for a specific platform (Java/Swift/Objective C) and communicates with the jаvascript environment via a bridge.

Compared to typical development for iOS and Android, React Native offers many other possibilities. Since your application is mostly jаvascript, there are many benefits you can take advantage of. For example, in order to see the changes added to the code, you can immediately “refresh” the application without waiting for the build to complete.

Most standard UI elements have components in RN, such as View = UIView in iOS, so it should be easy to implement UI frills if you have knowledge of React.

Why has RN become so popular?

- jаvascript is used to write the code, in particular React;
- it is possible to quickly write an application for both platforms. Less costs - more profitable for business;
- a large library of native and non-native components;
- for debugging, you can use the browser, there is also a hot-reload to quickly view the changes. There is no need to rebuild the application when making changes to the code;
- for rendering components, native components of the system used are used (for example, UIImage / ImageView), respectively, the performance of such a UI is higher than when using webview;
- just write your own library for RN, using the native functionality of the system;
- Another reason why RN has gained popularity in recent years is that it is used by such giants as Facebook, Instagram, Skype, Tesla, Baidu, Bloomberg, etc.

First application



Let's try to write our first application and understand what is needed for this. Let it be, for example, an application for displaying and searching for different users.

We will need the npx cli utility that comes with Node.js, Android Studio if we want to test the application on Android, or Xcode if on the iPhone. You can read more about how to install these tools here .

Let's start by creating a project with the command npx react-native init RandomGuysApp. You can also add TypeScript to an RN application, but we won't do that here.

After some time, we have created such a folder structure

How to develop your first app with React Native

We write in the console yarn add @react-navigation/native @react-navigation/stack react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view. This will install the navigation library so that you can navigate between application screens and dependencies for it. I decided not to include Redux, or another library for managing state, because I think that in our example it would be a bit redundant. After installation, if you are going to run the application on iOS, you need to go to the folder iosand write pod install(after installing cocoapods on your computer).

In index.jsit is written:

AppRegistry.registerComponent(appName, () => App);

this shows that the component Appis the entry point to our application. I prefer to store the code in a separate folder, so I will transfer it App.jsto a new folder - srcby changing the index.jspath before it to

import {App} from './src/App';

How to develop your first app with React Native

Let's start by creating a router. In the browser, when the user clicks on a link, the URL is added to the navigation history stack, and when the user presses the back button, the browser removes the last visited address from the stack. There is no such concept in RN by default, this is what React Navigation is for. An application can have multiple stacks. For example, each tab inside the application can have its own history of visits, but there can be one.

Let's create a folder navigators, and in it RootNavigator.js, in which we will place this code


import * as React from 'react';
import {createStackNavigator} from '@react-navigation/stack';
import {PersonListScreen} from '../screens/PersonListScreen';

const Stack = createStackNavigator();

export const RootNavigator = () => {
	return (
	<Stack.Navigator initialRouteName={'list'}>
		<Stack.Screen name={'list'} component={PersonListScreen} />
	</Stack.Navigator>
	);
};


A couple of points:

- the component ListScreendoes not yet exist;
- the application is expected to have only two screens, so it is somewhat simplified structurally to demonstrate how to work with RN.

What's going on here? A new navigation stack is created, which specifies the list of screens that are in it. It also specifies the start screen of the stack. Since we will have only one stack, in fact this will be the start screen of the application.

Let's move on to creating the first screen. Add a folder screensin which we will create a filePersonListScreen



We put the following code there:


import React, {Component} from 'react';
import {FlatList, View, StyleSheet} from 'react-native';
import {PersonListItem} from '../components/PersonListItem';

export class PersonListScreen extends Component {
	state = {
		list: [],
		isLoading: false,
	};

	componentDidMount = () => {
		this.onRefresh();
	};

	getMoreData = (isRefreshing) => {};

	onRefresh = () => {
		this.getMoreData(true);
	};

	onScrollToEnd = ({distanceFromEnd}) => {
		if (distanceFromEnd < 0) {
			return;
		}
		this.getMoreData(false);
	};

	onItemPress = (item) => {
		this.props.navigation.navigate('info', {person: item});
	};

	keyExtractor = (person) => person.login.uuid;

	renderItem = ({item}) => {
	return (
		<PersonListItem
			person={item}
			onPress={this.onItemPress.bind(this, item)}
		/>
		);
	};

	render = () => {
	const {isLoading, list} = this.state;

	return (
		<View style={styles.container}>
		<FlatList
			data={list}
			renderItem={this.renderItem}
			keyExtractor={this.keyExtractor}
			refreshing={isLoading}
			onRefresh={this.onRefresh}
			onEndReached={this.onScrollToEnd}
			onEndReachedThreshold={0.2}
		/>
		</View>
	);
	};
}


Again, PersonListItemit doesn't exist yet, but it's temporary. FlatList, is an efficient component for rendering lists - it supports PullToRefresh, scrolling to a list item by index, performance rendering by disabling rendering of components that are too far away from the visible screen area, and much more. Of course, the same elements in a column / row can be drawn in another way, for example, through ScrollView, but this is the most efficient way.

Each element of the renderItemarray from props is passed datato and the list component is returned. keyExtractorit's essentially the equivalent of a property key, only in the form of a function called for each element.

So, when entering the page, we are going to get a list of users, and draw it. When the list goes down, update it, and when we reach its end, load new data. Let's go back to for now PersonListItem, add it to the componentsfile PersonListItem.jsand fill it with this code


import React, {Component} from 'react';
import {StyleSheet, TouchableOpacity, Image, Text, View} from 'react-native';
export class PersonListItem extends Component {
	render = () => {
	const {onPress, person} = this.props;

	return (
		<TouchableOpacity style={styles.container} onPress={onPress}>
		<Image
			source={{uri: person.picture.medium}}
			resizeMode={'contain'}
			style={styles.avatar}
		/>
		<View style={styles.col}>
			<Text style={styles.name}>
			{person.name.first} {person.name.last}
			</Text>
			<Text style={styles.email}>{person.email}</Text>
		</View>
		</TouchableOpacity>
	);
	};
}

const styles = StyleSheet.create({
	container: {
		flexDirection: 'row',
		alignItems: 'center',
		padding: 12,
		borderBottomColor: '#b0b0b0',
		borderBottomWidth: 0.4,
	},
		avatar: {
		width: 50,
		height: 50,
		borderRadius: 25,
	},
	col: {
		marginLeft: 10,
	},
	name: {
		fontSize: 16,
		color: '#2e2e2e',
	},
	email: {
		marginTop: 10,
		fontSize: 13,
		color: '#b0b0b0',
	},
});


There are no props in RN classNameand styles are passed in a prop style, but are declared through StyleSheet.create(). You can, of course, use an object as a style, but in this case, some internal performance optimizations will not apply.

Notice how bare numbers are used instead of pixels? Because by default, (density-independent pixels) are used as a unit of measurement , and you can use dpto convert to , but we don’t really need this. In principle, almost all style properties duplicate CSS, so there should not be any particular problems. But there is such a feature - all components in RN have . Still there , there are no other options. The main difference is that all components have by default , unlike the browser version. There are a few more differences, but I won’t list them; in general, we can say that RN is somewhat truncated.pxPixelRatio.getPixelSizeForLayoutSize()display: flexdisplay: noneflexDirection: columndisplay: flex

Let's go back to App.js. Replace the contents of the file with the following code


import React, {Component} from 'react';
import {SafeAreaView} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {RootNavigator} from './navigators/RootNavigator';

export class App extends Component {
	render = () => {
	return (
		<SafeAreaView>
		<NavigationContainer>
			<RootNavigator />
		</NavigationContainer>
		</SafeAreaView>
	);
	};
}

const styles = StyleSheet.create({
	container: {
	flex: 1,
	},
});


We use our created router so that navigation works for us. The component is also used here SafeAreaView, it is needed so that the content in iOS is drawn inside the “safe” screen borders and, for example, does not run into the “unibrow” in the iPhone X.

Assembly and launch



Let's try to build and run what we have. If you have macOS, then you can use Xcode. To do this, when opening a project, you need to specify a file ios/RandomGuysApp.xcworkspaceinside the project. If Android, then you need to install the JDK and the necessary SDKs. The easiest way is to open the folder androidin Android Studio and the IDE will install the required software. And after that write in the root folder of the project npx react-native run-android.

When the project starts, something like this should appear on the screen.



This is the title screen listthat we have registered in the navigator. But there is still empty, because we still have nothing to draw. Therefore, let's go back to PersonListScreen.jsand add getMoreData()code to the function to receive data.


getMoreData = (isRefreshing) => {
	const limit = 15;
	const offset = isRefreshing ? 0 : this.state.list.length;
	const page = Math.ceil(offset / limit) + 1;
	fetch(`https://randomuser.me/api/?seed=foobar&results=15&page=${page}`)
	  .then((r) => r.json())
	  .then((json) => {
		this.setState({
		  list: isRefreshing
			? this.state.list.concat(json.results)
			: json.results,
		});
	  })
	  .catch((e) => {
		console.log(e);
	  });
  };


You can use either react-native-debugger or a browser to debug an application. The debugger is activated by a key combination ctrl(cmd) + Mfor Android, cmd + Dfor iOS. You can also enable live reload there.

From above to importfrom react-native add module importStyleSheet

import {FlatList, View, StyleSheet} from 'react-native';

At the bottom of the same file add


const styles = StyleSheet.create({
	container: {
	  flex: 1,
	},
  });


and add this style to our View. We get something like this



When the screen is pulled down, the list is updated, when scrolling, it is reloaded. Let's add the ability to go to the user's card.


onItemPress = (item) => {
	this.props.navigation.navigate('info', {person: item});
};


This is a transition to the screen with the name infowith the transfer of the selected user as a parameter. In the future, it can be obtained from the screen component. Now let's add this screen to the navigator RootNavigator.jsand write the code for it.


...
import {PersonInfoScreen} from '../screens/PersonInfoScreen';
...
<Stack.Screen name={'list'} component={PersonListScreen} />
<Stack.Screen name={'info'} component={PersonInfoScreen} />
...


Let's create a file src/screens/PersonInfoScreen.jsand add the following code there.


import React, {Component} from 'react';
import {StyleSheet, View, Image, Text} from 'react-native';

export class PersonInfoScreen extends Component {
	renderRow = (cells) => {
	return cells.map((cell) => (
		<View style={styles.cell} key={cell.title}>
		<Text style={styles.cellTitle}>{cell.title}</Text>
		<Text style={styles.cellValue}>{cell.value}</Text>
		</View>
	));
	};

	render = () => {
	const {person} = this.props.route.params;

	return (
		<View style={styles.container}>
		<Image
			source={{uri: person.picture.large}}
			style={styles.avatar}
			resizeMode={'contain'}
		/>
		{this.renderRow([
			{title: 'login', value: person.login.username},
			{title: 'name', value: person.name.first},
			{title: 'surname', value: person.name.last},
			{title: 'email', value: person.email},
			{title: 'phone', value: person.cell},
		])}
		</View>
	);
	};
}

const styles = StyleSheet.create({
	container: {
		flex: 1,
		alignItems: 'center',
	},
	avatar: {
		width: 100,
		height: 100,
		borderRadius: 50,
		marginTop: 20,
	},
	cell: {
		marginTop: 15,
		justifyContent: 'center',
		alignItems: 'center',
	},
	cellTitle: {
		fontSize: 13,
		color: '#b0b0b0',
	},
	cellValue: {
		marginTop: 10,
		fontSize: 16,
		color: '#2e2e2e',
	},
});


Here's what we got.



Thus, we made an application for displaying and viewing some information about different people.

Resources


There are many resources available for learning RN, here is a short list:

- Official documentation , here you can find descriptions of all APIs and built-in components of the library.
- One of the best courses to learn React Native. It will help you quickly understand it, and also teach you to understand the RN and React ecosystem as a whole.
- There is a large list of cool libraries for various occasions and articles on the topic.

Eventually



React Native is a powerful framework used by businesses of all sizes to build mobile apps. It's a fast, efficient, and relatively easy way to build jаvascript applications. Its main advantage is that it allows you to quickly create an application for several platforms at the same time, and also has a low entry threshold. React Native is widely used by big brands, so don't worry about it going anywhere in the next couple of years.

Related Articles

Add Your Comment

reload, if the code cannot be seen

All comments will be moderated before being published.