DEV Community

John Vester
John Vester

Posted on

Leveraging Salesforce Using Mobile Applications Written (Once) In React Native

Salesforce Tower - Indianapolis

In the “Leveraging Salesforce Using Spring Boot” article, I navigated the course for introducing a Spring Boot service that would leverage the well-established Salesforce RESTful API. The goal of this service is to act as a middleware layer to allow clients not written in Salesforce to retrieve and update contact data stored in Salesforce. This backend service implements its own caching layer to provide a faster response time and also cut down on the number of times Salesforce needed to be called.

In the “Leveraging Salesforce Using a Client Written In Svelte” article, I introduced a simple client written in Svelte, which provided the ability to make updates to the Salesforce data using an inline editor—again, without actually using the Salesforce client.

The “Leveraging Salesforce Using a Client Written In Vue.js” article introduced a client application using the Vue.js framework to further interact with the Spring Boot service. Using Vue.js, the resulting client is able to not only read data from Salesforce but to process and display updates made to the Salesforce data via a server-sent events (SSE) implementation.

In this article, we will use React Native to provide native client applications for Android and iOS devices, leveraging a single code base.

Revisiting the Example Use Case

To recap our example use case, the Business Call Center is about to launch a major marketing campaign. However, they recently discovered that the title noted for the list of contacts was incorrect approximately 90% of the time.

A team of interns has been updating contacts using the Svelte client, and the managerial team has been using the Vue.js client to monitor the updates as they occur, complete with server-sent events appearing as toast messages.

It was recently brought to our attention that the C-suite would like to have insight into the contact information as well. Of course, executives use mobile phones daily. After viewing the existing clients using the browser on their mobile devices, the executives wanted to offer a native application that runs on both Android and iOS devices.

As a result, the following use case has been approved for development:

  1. Native application that runs on both Android and iOS devices (browser-based application is not desirable)
  2. Display a simple list of contacts
  3. There is no expectation to edit contact information at this time
  4. There is no expectation to search contacts at this time

As one might expect, this work is critical and needs to be completed as soon as possible.

Why React Native?

React Native is a JavaScript-based client framework that provides a write-once approach to designing native applications that can run on both Android and iOS devices. Created by Facebook, React Native has been adopted by technology giants such as Instagram, Coinbase, Shopify, Uber Eats, and even Salesforce.

Some of the benefits from using React Native are noted below:

  • Faster speed to market in those cases where multiple native applications are required.
  • No need to maintain skills for multiple languages, allowing focus just on Javascript and some native APIs.
  • Transforming a web page to a native application is far easier than trying to accomplish the same tasks in Android Studio and Xcode.

In our example use case, all three benefits for selecting React Native will be a primary strength in providing this new functionality.

Getting Started with React Native

There are several ways to begin setting up your environment to develop with React Native:

  • React Native CLI Quickstart (works with Android Studio and Xcode)
  • Expo CLI Quickstart (requires only Node.js and a phone or emulator)

Because the React Native documentation indicates that Expo CLI is the easiest way to get started, that is the path I selected for this article.

I first needed to install the Expo CLI using the following command:

npm install -g expo-cli

After installing the Expo CLI, I created a new React Native project using the Expo CLI:

expo init SalesforceIntegrationReactNative

Executing this command provided a command-based wizard for me to follow:

? Choose a template: › - Use arrow-keys. Return to submit.
    ----- Managed workflow -----
❯   blank               a minimal app as clean as an empty canvas
    blank (TypeScript)  same as blank but with TypeScript configuration
    tabs (TypeScript)   several example screens and tabs using react-navigation and TypeScript
    ----- Bare workflow -----
    minimal             bare and minimal, just the essentials to get you started

    Your project is ready!

    To run your project, navigate to the directory and run one of the following npm commands.

    - cd SalesforceIntegrationReactNative

    - npm start # you can open iOS, Android, or web from here, or run them directly with the commands below.
    - npm run android
    - npm run ios
    - npm run web
Enter fullscreen mode Exit fullscreen mode

Before I went any further, I decided to rename the folder from the default value of “SalesforceIntegrationReactNative” to “salesforce-integration-react-native”. I am not sure if this breaks some React development rule, but I wanted to follow my self-imposed naming convention for my projects on GitLab.

At this point I was able to use the “npm run web” command to show the React Native application:

Hello World

Of course, there is not a lot there, but at least the React Native application started in a matter of seconds.

Adding Some Dependencies

For this simple mobile application, I only needed to include two dependencies in order to meet the business needs:

I was able to install these components very quickly using npm:

npm i axios react-native-table-component --save

With all the necessary elements in place, I can focus on creating the Contacts view in React Native.

Creating the Contacts Component

Upon starting the mobile application, I wanted to provide feedback to the user that the contacts were being retrieved from the Spring Boot RESTful API. I used the ActivityIndicator in React Native to show a spinner while accessing data.

Since I will be running locally and the Spring Boot caching will provide the results even faster, my design of the Contacts component utilizes a hard-coded two-second delay to make sure the activity indicator is visible to the user.

To get started, I created a Contacts component using my IntelliJ IDE:

export default class Contacts extends Component { }

Next, I established some basic styling to add some flair to the resulting view of data:

const styles = StyleSheet.create({
    container: { flex: 1, padding: 16, paddingTop: 30, backgroundColor: '#fff' },
    head: { height: 40, backgroundColor: '#f1f8ff' },
    headerText: { margin: 6, fontWeight: 'bold' },
    text: { margin: 6 },
    loadingText: { color: '#1798c1', marginTop: 15 }
});
Enter fullscreen mode Exit fullscreen mode

For the application state, I wanted to keep track of a loading boolean property, plus lists for the table heading and table data. I populated the default constructor as follows:

constructor(props) {
        super(props);
        this.state = {
            loading: true,
            tableHead: ['Name', 'Department', 'Title'],
            tableData: []
        }
    }
Enter fullscreen mode Exit fullscreen mode

For this simple application, I decided to use the componentDidMount() internal function to make the call to the Spring Boot RESTful service:

componentDidMount() {
        this.setState({
            loading: true,
            tableData: []
        });

        axios.get("http://192.168.1.212:9999/contacts")
            .then(response => {
                setTimeout(() => {
                    this.setState({
                        tableData: this.createTableData(response.data),
                        loading: false
                    })
                }, 2000)
            })
            .catch(error => {
                console.log(error);
            });
    }
Enter fullscreen mode Exit fullscreen mode

As you can see, once the data arrives, the loading boolean is set to false. Also, you’ll notice how the two-second hard-coded setTimeout() delay forces the activity indicator to load.

For simplicity, I created a function to transform the Salesforce data to match the format expected by the react-native-table-component:

createTableData = (contacts) => {
        let tableData = [];
        if (contacts) {
            for (let i = 0; i < contacts.length; i++) {
                tableData.push([contacts[i].Name,
                    contacts[i].Department ? contacts[i].Department : "(not set)",
                    contacts[i].Title ? contacts[i].Title : "(not set)"]);
            }
        }

        return tableData;
    }
Enter fullscreen mode Exit fullscreen mode

Finally, I added the built-in render() function to provide view data to the end user:

render() {
        const state = this.state;
        return (
                <View style={styles.container}>
                    <Table borderStyle={{borderWidth: 2, borderColor: '#c8e1ff'}}>
                        <Row data={state.tableHead} style={styles.head} textStyle={styles.headerText}></Row>
                        <Rows data={state.tableData} textStyle={styles.text}></Rows>
                    </Table>

                    { state.loading &&
                        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', padding: 30 }}>
                            <ActivityIndicator size='large' color='#1798c1' ></ActivityIndicator>
                            <Text style={ styles.loadingText }>Loading Contacts from Salesforce ...</Text>
                        </View>
                    }
                </View>
        )
    }
Enter fullscreen mode Exit fullscreen mode

The last thing we need to do is connect the Contacts component to the React Native application. I updated the App.js file as shown below:

import React from 'react';
import Contacts from "./Contacts";

const App = () => {
  return (
      <>
        <Contacts ></Contacts>
      </>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Using the React Native Component on Mobile Devices

With the Contacts component ready to go, I started the React Native application using iOS emulation mode using the following command:

npm run ios

The Metro bundler started and utilized the iPhone emulator I had set up on my local system.

Metro Bundler

I also used the “Run on Android device/emulator” link to launch an Android device. On my second display, the following emulators presented the activity indicator spinners:

Loading Data

After the hard-coded two-second delay, both devices displayed the list of contacts in a native application:

Showing Data

Conclusion

Starting in 2021, I have been trying to live by the following mission statement, which I feel can apply to any IT professional:

“Focus your time on delivering features/functionality which extends the value of your intellectual property. Leverage frameworks, products, and services for everything else.”

  • J. Vester

In this article, I created a Contacts component by leveraging React Native, which can be utilized to build a native application that can run on both Android and iOS devices. Similar to my experiences with Svelte and Vue.js, the time to create a ready-to-deploy component was very fast, measuring in minutes rather than hours. Just like in all of the articles in this series, we have been able to use Salesforce without actually using a Salesforce client.

Of course, a production-ready scenario would require some additional work to prepare this application for “prime time” use.

If you are interested in the source code used for the React Native client, simply navigate to the following repository on GitLab:

https://gitlab.com/johnjvester/salesforce-integration-react-native

Future articles are also planned for the following other JavaScript-based clients:

  • Angular
  • Lightning Web Components (outside the Salesforce ecosystem)

Have a really great day!

Top comments (0)