Services in React Native: Best Practices and Examples

React Native is a popular framework for developing mobile apps with JavaScript and React. It allows developers to create apps for both the Android and iOS platforms with a single codebase.

The ability to effectively manage services is important when developing strong and scalable systems. Services in React Native include functions like data retrieval, background operations, network queries, and integration with native modules.

This article provides a full overview of services in React Native, including examples, services in React Native GitHub, and how to create an unstoppable service in React Native using Headless JS.

How to Create Services in React Native

Creating services in React Native entails establishing the service functions or classes and incorporating them into your components.

To build an API service, you usually develop a module that handles HTTP requests. Here’s an example with Axios:

javascript

// apiService.js

import axios from 'axios';

const API_BASE_URL = 'https://api.example.com';

const apiService = {

getData: async (endpoint) => {

try {

const response = await axios.get(`${API_BASE_URL}/${endpoint}`);

return response.data;

} catch (error) {

console.error('Error fetching data:', error);

throw error;

}

},

postData: async (endpoint, data) => {

try {

const response = await axios.post(`${API_BASE_URL}/${endpoint}`, data);

return response.data;

} catch (error) {

console.error('Error posting data:', error);

throw error;

}

},

// Add other methods (put, delete) as needed

};

export defaultapiService;

How to Integrate the API Service

To integrate the API service into a React Native component, import it and call its methods from your component’s lifecycle or event handlers.

javascript

// MyComponent.js

import React, { useEffect, useState } from 'react';

import { View, Text, Button } from 'react-native';

import apiService from './apiService';

const MyComponent = () => {

const [data, setData] = useState(null);

useEffect(() => {

fetchData();

}, []);

const fetchData = async () => {

try {

const result = await apiService.getData('endpoint');

setData(result);

} catch (error) {

console.error('Error fetching data:', error);

}

};

const handlePostData = async () => {

try {

const postData = { key: 'value' };

const result = await apiService.postData('endpoint', postData);

console.log('Post result:', result);

} catch (error) {

console.error('Error posting data:', error);

}

};

return (

<View>

<Text>Data: {data ? JSON.stringify(data) : 'Loading...'}</Text>

<Button title="Post Data" onPress={handlePostData} />

</View>

);

};

export default MyComponent;

How to Create a State Management Service with Redux

State management is an important part of every React Native application. Redux is a widely used library for managing state in React Native apps. Here’s how to build and use a state management service with Redux.

javascript

// actions.js

export const fetchData = () => {

return async (dispatch) => {

dispatch({ type: 'FETCH_DATA_REQUEST' });

try {

const data = await apiService.getData('endpoint');

dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });

} catch (error) {

dispatch({ type: 'FETCH_DATA_FAILURE', error });

}

};

};

// reducers.js

const initialState = {

data: null,

loading: false,

error: null,

};

const dataReducer = (state = initialState, action) => {

switch (action.type) {

case 'FETCH_DATA_REQUEST':

return { ...state, loading: true, error: null };

case 'FETCH_DATA_SUCCESS':

return { ...state, loading: false, data: action.payload };

case 'FETCH_DATA_FAILURE':

return { ...state, loading: false, error: action.error };

default:

return state;

}

};

export default dataReducer;

// store.js

import { createStore, applyMiddleware } from 'redux';

import thunk from 'redux-thunk';

import dataReducer from './reducers';

const store = createStore(dataReducer, applyMiddleware(thunk));

export default store;

How to Integrate the State Management Service

To integrate the state management service, link your components to the Redux store.

javascript

// App.js

import React from 'react';

import { Provider } from 'react-redux';

import store from './store';

import MyComponent from './MyComponent';

const App = () => (

<Provider store={store}>

<MyComponent />

</Provider>

);

export default App;

// MyComponent.js

import React, { useEffect } from 'react';

import { useSelector, useDispatch } from 'react-redux';

import { View, Text, Button } from 'react-native';

import { fetchData } from './actions';

const MyComponent = () => {

const dispatch = useDispatch();

const data = useSelector(state => state.data);

const loading = useSelector(state => state.loading);

const error = useSelector(state => state.error);

useEffect(() => {

dispatch(fetchData());

}, [dispatch]);

return (

<View>

{loading ? (

<Text>Loading...</Text>

) : error ? (

<Text>Error: {error.message}</Text>

) : (

<Text>Data: {JSON.stringify(data)}</Text>

)}

<Button title="Reload Data" onPress={() => dispatch(fetchData())} />

</View>

);

};

export default MyComponent;

What are the React Services Examples?

Here is a collection of React syntax and services in React examples that you can use as a guide or reference.

React.js supports reusable components. You can add value to props, as seen below:

function Welcome(props) {

return <h1>Hello, {props.name}</h1>;

}

const element = <Welcome name="Hackemist" />;

ReactDOM.render(

element,

document.getElementById('root')

);

The name “Hackemist” will be assigned to {props.name} by the function Welcome(props), resulting in a component with the value “Hackemist”. After that, React will convert the element to HTML.

Other ways to declare components:

There are numerous ways to declare components in React.js. There are two types of components: stateless and stateful components.

  • Stateful
  • Class Type Components
class Cat extends React.Component {

constructor(props) {

super(props);

this.state = {

humor: 'happy'

}

}

render() {

return(

<div>

<h1>{this.props.name}</h1>

<p>

{this.props.color}

</p>

</div>

);

}

}

 

  • Stateless Components
  • Functional Components (Arrow Function from ES6)
const Cat = props => {

return (

<div>

<h1>{props.name}</h1>

<p>{props.color}</p>

</div>;

);

};

Implicit Return Components

const Cat = props =>

<div>

<h1>{props.name}</h1>

<p>{props.color}</p>

</div>;

Fragments allow you to render several components without utilizing a wrapper element. When you try to render items in JSX without an enclosing tag, you’ll get the error message Adjacent JSX elements must be wrapped in an enclosing tag.

This is because when JSX transpiles, it creates elements with their associated tag names and is unable to determine which tag name to use if many elements are encountered.

Previously, a common method was to create a wrapper div to address this issue. However, the inclusion of Fragment in React 16 made this unnecessary.

Fragment serves as a wrapper without introducing superfluous divs to the DOM. You may either utilize it directly from the React import or disassemble it.

import React from 'react';

class MyComponent extends React.Component {

render(){

return (

<React.Fragment>

<div>I am an element!</div>

<button>I am another element</button>

</React.Fragment>

);

}

}

export default MyComponent;

// Deconstructed

import React, { Component, Fragment } from 'react';




class MyComponent extends Component {

render(){

return (

<Fragment>

<div>I am an element!</div>

<button>I am another element</button>

</Fragment>

);

}

}

export default MyComponent;

React version 16.2 simplified this process further, allowing for empty JSX tags to be interpreted as Fragments:

return (

<>

<div>I am an element!</div>

<button>I am another element</button>

</>

);

Services in React Native GitHub

When investigating services in React Native, particularly those published on GitHub, you’ll come across a diverse set of libraries, tools, and repositories that improve and expand the functionality of your mobile applications.

These services can include authentication solutions, database connectors, API clients, analytics tools, and more.

Most mobile applications require authentication to manage user identities and provide safe access. GitHub has various packages and services that enable authentication in React Native applications:

  • Firebase Authentication: Firebase provides a robust authentication solution that accepts email and passwords, social logins (Google, Facebook, and others), and more. It is frequently utilized in React Native due to its simplicity of integration and extensive feature set.
  • Auth0 React Native SDK: Auth0 offers a modular identity platform that seamlessly interacts with React Native applications. Their SDK on GitHub includes features like single sign-on, multifactor authentication, and user management.
  • AWS Amplify Auth: For developers that use AWS services, Amplify offers authentication and authorization capabilities that work well with React Native. It supports a variety of authentication mechanisms and can be configured rapidly using its CLI.

Services in React Native GitHub Example

Step 1: First, make sure you have a React Native project set up. You can start a new project with:

bash

npx react-native init MyProject

cd MyProject

Step 2: Create a new file called UserService.js in the project directory. This file will store our service logic.

javascript

// UserService.js

const users = [

{ id: 1, name: 'John Doe', email: 'john@example.com' },

{ id: 2, name: 'Jane Smith', email: 'jane@example.com' },

];

export const getUsers = () => {

return new Promise((resolve, reject) => {

// Simulate an API call with setTimeout

setTimeout(() => resolve(users), 1000);

});

};

export const getUserById = (userId) => {

return new Promise((resolve, reject) => {

const user = users.find(u => u.id === userId);

if (user) {

setTimeout(() => resolve(user), 500);

} else {

setTimeout(() => reject(new Error('User not found')), 500);

}

});

};

export const addUser = (name, email) => {

return new Promise((resolve, reject) => {

// Simulate adding user to the list

const newUser = { id: users.length + 1, name, email };

users.push(newUser);

setTimeout(() => resolve(newUser), 500);

});

};

export const updateUser = (userId, name, email) => {

return new Promise((resolve, reject) => {

let updatedUser = null;

users.forEach(user => {

if (user.id === userId) {

user.name = name;

user.email = email;

updatedUser = user;

}

});

if (updatedUser) {

setTimeout(() => resolve(updatedUser), 500);

} else {

setTimeout(() => reject(new Error('User not found')), 500);

}

});

};

export const deleteUser = (userId) => {

return new Promise((resolve, reject) => {

const index = users.findIndex(u => u.id === userId);

if (index !== -1) {

const deletedUser = users.splice(index, 1)[0];

setTimeout(() => resolve(deletedUser), 500);

} else {

setTimeout(() => reject(new Error('User not found')), 500);

}

});

};

How to create an unstoppable service in React Native using Headless JS

Step 1: Creating the Bridge

To gain a thorough understanding, I will provide a brief overview of how to construct a bridge to a native module in RN. If you prefer an automated process or want a quicker way to achieve this, I recommend react-native-create-bridge. If you are already familiar with this step, you may skip straight to step 2.

In practice, a bridge serves as a conduit for communication between the RN and native layers. As stated in the manual, the first step in creating a bridge is to supply a Package responsible for registering your module or UI module (not used here) in the RN layer. As illustrated in the class below, the module is instantiated with the React context as a parameter.

The Module is in charge of specifying the methods and properties that will be available to the RN layer in the native layer. To expose a Java method, it must be annotated with @ReactMethod, and the return value is always void. Because the bridge is asynchronous, the only way to send a result to the RN layer is via callbacks or event emitters.

To finish the bridge, simply attach it to the two sides. The new module must be instantiated in the getPackages method of the MainApplication.java file in the android subdirectory, which is automatically created by the RN project. Once you’ve done this, the module’s methods and properties will be ready for import and use, as seen below.

// Heartbeat.jsimport { NativeModules } from ‘react-native’;const { Heartbeat } = NativeModules;export default Heartbeat;

Step 2: Creating the Service

As previously stated, a service is used to execute tasks that are not part of the application’s main thread. In this example, the created service is responsible for sending heartbeat events at regular intervals after it is launched.

There are several ways to build an interval in Android, but in my case, I make use of a Handler to process a runnable object and transmit the event every two seconds. The

RCTDeviceEventEmitter can send events to the RN layer and can be retrieved straight from the react context.

The documentation for Android Services is extremely clear about how the Android System Manager will affect your service. If it detects that your device is in critical mode, such as low memory or battery, it will terminate some services to free up resources.

To prevent this, you must switch your service to Foreground Mode, which requires a notification to be displayed on the device’s status bar.

Step 3: Creating the BroadcastReceiver

A BroadcastReceiver, as the name suggests, is a responsive component that broadcasts messages from the Android system or other apps, similar to the publish-subscribe design pattern. There are other broadcast messages accessible in an Android system, but the BOOT_COMPLETED message is the most significant in our situation. It indicates that the device underwent a reboot operation and that this process is complete.

Listening to this specific message, the broadcast receiver will be able to restart the service that was built before the device reboot procedure, allowing it to continue sending heartbeat events.

The implemented code is displayed below:

// BootUpReceiver.javapublic class BootUpReceiver extends BroadcastReceiver {@Override

public void onReceive(Context context, Intent intent) {

context.startService(new Intent(context, HeartbeatService.class));

}

}

In addition, the AndrodManifest.xml file must declare the broadcast receiver and provide the message to which it will listen. To read this type of message, the appropriate permissions must also be granted.

Step 4: Creating the Application

This is certainly the simplest stage in this tutorial, but it is also the most fascinating. It demonstrates the outcome of everything done thus far. In the RN layer, we need to develop a component that interacts with and displays the user’s heartbeat events, and I felt that the best example for this event would be a heart pulse action, so let’s do that.

Simple enough, right? Furthermore, pressing a button component invokes the startService method from the native layer.

Step 5: Creating the Headless Service

Headless JS is an RN service that can encapsulate specific javascript operations and execute them independently from the application, similar to an Android service. The headless service can perform any type of operation, excluding UI operations. In the actual scenario, the headless service can replace the RCTDeviceEventEmitter, eliminating the need for React Context in the native layer.

A headless service must be registered on AppRegistry, and as stated in the documentation, each app registry should be required early in the required sequence to ensure that the JS execution environment is established before additional modules are required. In index.js, we call the registry, as seen below.

// index.jsAppRegistry.registerHeadlessTask(‘Heartbeat’, () => MyHeadlessTask);

Now, MyHeadlessTask is in charge of changing the width and height of the heart image based on the current condition. I chose Redux over hooks because we have a centralized state that is shared with the App component. To properly set the state, simply create the fundamental redux structure (action, reducer, and store).

FAQs

What are services in React?

In React, a service is often a collection of methods that perform data gathering, processing, or any other functionality unrelated to UI rendering.

How do you run a background service in React Native?

import BackgroundService from ‘react-native-background-actions’; const sleep = (time) => new Promise((resolve) => setTimeout(() => resolve(), time)); // You can perform anything in your task, such network requests, timers, and so on, // as long as it does not influence the user interface.

What is React Native app development services?

React Native programming is ideal for apps that require a strong user interface. It enables us to create a user-friendly interface that works perfectly on both iOS and Android. Shared business logic improves process efficiency and coherence.

What are Microservices in React?

Microservices are a sort of software architecture in which huge programs are composed of small services. React is a JavaScript library that creates user interfaces. There are a few drawbacks to employing microservices in React JS app development.

Which UI library is best for React Native?

The greatest React Native styling libraries include NativeBase, React Native Elements, React Native Paper, and React Native UI Kitten. You can construct your mobile app using any of these methods.

Leave a comment

Index