In this tutorial, you are going to get started in creating a mobile application using React Native. The application we are going to develop will be a split bill calculator. This split bill calculator computes the amount one has to pay for a service after giving out a tip and splitting the bill with the number of persons using the service. This application requires a user to:

  • Enter the amount to pay.
  • Adjust the percentage of the billed amount percentage as the tip.
  • Specify the number of people to split the bill.

Prerequisites

Knowledge of the following technologies is required to follow this guide:

  • JavaScript (ES6+)
  • React fundamentals

What you will Learn

  • How to create a React Native application
  • Using flex layout React Native application
  • Managing application state in React
  • Handling user input in React Native

Application setup

Set up your React Native development environment using the guide at https://reactnative.dev/docs/next/environment-setup.  Select the Expo CLI Quickstart guide tab since this tutorial uses Expo command-line interface to create the split bill calculator.

Install Visual Studio Code as you'll be using it as your development IDE.

Introduction

React Native is a mobile application framework used to develop Android, iOS, and Web applications. React Native enables one to create native applications using both JavaScript and React. As a software developer using React Native, you can use a single code base to deploy your applications to both Android and iOS environments.

The split bill calculator illustrates the basic building blocks of a conventional React Native application. This application incorporates the following features:

  • Views
  • Text
  • TextInput
  • State
  • Flex Layout

Views are the basic building blocks of the user interface (UI). They act as containers to text, images, or user input.

Text displays strings of text while the TextInput allows a user to enter text input values into an application.

The State holds the information about the content one has to display on the screen or data one needs to manipulate for the application to work. Lastly, the Flex layout places content on a device's screen.

Getting Started

Use the Expo command-line interface (CLI) in your terminal to initialize the split bill calculator application and then choose the blank template from the list of options displayed on the terminal.

expo init SplitBillCalculator

Open the project in Visual Studio Code by executing the following commands in your terminal:

cd SplitBillCalculator
code .

At the root of the application folder, create a src directory with the component, containers, and screens directories inside it.

Directory structure
Directory structure

Create an application entry file,  index.js, at the root of the application directory and register the App.js file to be the root component by adding the following content to the index.js file:

Move the App.js file into the src directory and update the value of the main script tag in the package.json to index.js:

{
  "main": "index.js"
}

Start the application by executing the command npm start or yarn start on the terminal.

The output from the terminal  has  instructions to either to view the application using either of the following devices:

  • Android Emulator or iOS simulator.
  • Expo client application on your mobile phone device.

Building the Application Layout

Split bill calculator wireframe
Split bill calculator wireframe

The above diagram displays the application sections:

  • BillInput
  • TipInput
  • SplitOutput

The sections above represent their respective components. Adopting this high-level view, you get to see the various React Native components used to display user data.

The BillInput and the TipInput sections have the same structure - they include a label and an input. These two sections will make use of one shared component called Input.js to display their respective views.

Create a new file called Input.js inside the ./src/components folder and add the following code to it:

The Input component accepts the following as its props:

  • label (title for the bill and tip input sections)
  • amount (user-entered value for the bill and tip amount)
  • placeHolderText (placeholder text for the text inputs)
  • handleTextChange (function containing logic for handling text change on the text inputs)

Considering the input type for both the bill and tip input sections will be numbered, the TextInput component keyboard type is specified to be numeric.

The Input component has a padding of 10 pixels for both the horizontal and the vertical sides. The font size of the label for the input component has a font size of 18 and a color of grey while the text input has a font size of 30 and a font-weight of 700 (equivalent to bold text).

All dimensions in React Native are unitless and represent density-independent pixels.

Looking keenly at the sketch of the tip input section, you'll notice that the text input value has a percentage displayed next to it. It's desirable that when a user enters text in the tip input, the percentage icon is displayed next to it.

The code snippet below shows how the percentage will be displayed next to the text input of the Input component if the label text will be equal to the string "Tip" using the conditional rendering technique. Update the code of the Input.js file to match the following modifications:

If the value of the label prop is not equal to the string Tip, then the percentage is not rendered on the screen. The text input and percentage views are initially stacked vertically. To display UI elements horizontally, one has to specify a flex-direction to a container holding those UI elements.

A View container with a style of inputContainer wraps both the text input and the percentage text. The inputContainer contents are stacked horizontally along the x-axis of the device's screen. The items of the inputContainer align vertically.

The section style of the Input component has a vertical margin of 10 so that both the bill and tip input sections have vertical spacing between them.

The SplitOutput container contains two components:

  • SplitCount - determines the number of persons to split the bill.
  • SplitTotal - outputs the resulting split amount to pay.

The SplitCount component has a label, an increment and decrement button, and a view to display the number of persons to split the bill.

The SplitTotal component has a label and the split bill amount value. The SplitOutput container has a background color of blue to give it a distinct look.

Create a new file with the name SplitOutput.js inside ./src/containers directory and add the following code to it:

In this file, the container View has a style of sectionOutput. The SplitCount and SplitTotal components appear next to each other horizontally. A justify-content value of "space-between" sets a uniform spacing between the two components. (View the sectionOutput style values).

The sectionOutput style then sets the background color, border-radius, and padding for the container View.

The split prop maps to the SplitCount component while the splitTotal maps to SplitTotal. The handleSplitAdd and the handleSplitRemove "props" are functions that are passed down to the SplitCount and SplitTotal components to handle text input changes.

Create the files SplitCount.js and SplitTotal.js files in the ./src/components folder.

Inside the SplitCount.js file, add the following code:

The SplitCount component two buttons and split count text are displayed horizontally with uniform spacing between them. MaterialIcons from Expo vector icons display the plus and minus icons.

The MaterialIcons has an onPress prop that accepts a function that executes on pressing the icon. The handleSplitAdd triggers on pressing the plus icon while the handleSplitRemove triggers on pressing the minus icon.

The minus icon is disabled when the split count value is less than 2; the count value cannot be a negative number.

Inside the SplitTotal.js file, add the following code:

The SplitTotal component takes only one prop, the splitTotal, which displays the amount to pay after splitting the bill.

To view the output, create a Home.js file inside the ./App/screens folder and add the following content:

The home screen spans the whole device screen by adding a flex of the value 1 to its container view. Top padding of 10 ensures that contents on the home screen appear below the status bar. The container view also has horizontal padding of the value 30 that guarantees consistent spacing on both sides of the screen.

The Input and SplitOutput components declare their text input values as regular variables. The reason for this is because the application is not managing its "state" yet.

The home screen declares text input handler functions used in the various text inputs in the application. These text input handler functions include:

  • handleBillChange
  • handleTipChange
  • handleSplitAdd
  • handleSplitRemove

The components inside the Home screen have props that accept the variables and the handler functions declared at the component level.

In the entry file of the application, App.js, import the home screen file to view the contents on the screen as follows:

The split bill calculator layout is now viewable on a physical mobile device or mobile phone emulator.

Managing Application State and Handling User Input

At the moment, users of the application have no way of calculating the split bill amount. This section will cover the remainder of the application logic that includes:

  • Managing application state
  • Manipulating user input data

You'll notice that when you try entering user input data, nothing changes in the resulting calculated split bill amount value. This problem can be solved by adding an application state and also updating the handler functions logic of the text inputs.

This application requires a way to update the UI and also track the values used to manipulate the data entered by the user. For us to add the application state, we'll leverage the use of the useState hook provided by React. The useState hook enables us to add an application state to our functional components.

Calling the useState hook returns a state variable and a function whose purpose is to update the application state. useState accepts an initial value as an argument to its function call. The general pattern for using useState is as follows:

const [value, setValue] = useState("");

The value is the state variable, while the setValue is the state updater function. The state variable initial value is an empty string. To fetch the value state variable and the setValue function, use the object-destructuring syntax.

Update the variable definitions in the Home.js file to reflect the following changes:

The bill, tip, split, and splitTotal variables are now state variables and have their corresponding state updater functions.

The value of the text inputs has to change when a user enters an input value in both the bill and tip form inputs. The bill input and tip input values have initial values of 0 and 10 respectively.

The TextInput component in React Native has an onChangeText prop that accepts a function as its value. This function is called every time a value in text input changes. The onChangeText prop value has the following syntax:

onChangeText={(value) => handleValueChange(value)}

// shorthand syntax
onChangeText={handleValueChange}

The form text input provides the value variable of the callback function that is equivalent to the text entered on user input.

In the Home.js file, implement the logic in the handler functions to update the application state of the bill and tip values when a user enters text in a form input element by calling the state updater function inside the text input handler functions:

Increasing and decreasing the tip count also follows the same pattern by updating the application state of split count inside the handler functions. However, note that the count has a string as its initial state value. So, we have to provide an implementation to change its value to an integer to update the new split count value.

The argument to the setSplit state updater function is a callback function that takes the initial split count state value as its argument and converts it to an integer. To update the count state, cast the resulting count after an increment/decrement operation back to a string.

The split total amount is not visible yet to our users. To do that, we have to provide functionality where we add the bill amount to the tip amount, then divide the resulting value by the split count. To find the tip amount, multiply the bill amount by the tip percentage.

In the tip calculator application, we have to take into account the following operations:

  • Entering bill amount
  • Entering tip percentage
  • Increasing or decreasing split count

The above operations are side-effects in a React application. The useEffect hook from React enables us to manage these side effects. To track changes in the user interface output values, place the logic to calculate the resulting total amount inside the useEffect hook.

A default value of 0 is provided for the bill, tip, and split amounts when the user clears the text input. The bill is cast into a float value while both the tip and split count converted into integers. The split total amount of precision is to two decimal places according to the design specification. When updating the application state of the total amount to pay, cast back the resultant value to a string

Provide a dependency array as an argument to the useEffect hook with the bill, tip, and split counts as its values. This dependency array ensures that if the application state changes, the useEffect hook is run, and then the UI is updated.

Finally, wrap the home screen container View with a TouchableWithoutFeedback component and then provide the functionality to dismiss the keyboard when pressing the view outside the keyboard.

Split bill calculator demo
Split bill calculator demo

Visit the URL https://github.com/khwilo/SplitBillCalculator to view the code to this split bill calculator application.

Conclusion

From this tutorial, you have learned:

  • How to create a React Native application
  • Using flex layout React Native application
  • Managing application state in React
  • Handling user input in React Native

I hope this guide has interested you in trying out React Native for your next mobile application project. Tweet me @khwilo and share with me the lessons you have learned from this tutorial.

References

You've successfully subscribed to Decoded For Devs
Welcome back! You've successfully signed in.
Great! You've successfully signed up.
Your link has expired
Success! Your account is fully activated, you now have access to all content.