Skip to main content

Command Palette

Search for a command to run...

Building a Currency Converter using React Native

Updated
•4 min read•View as Markdown
Building a Currency Converter using React Native
T
Currently, I'm working as an AI Intern in the healthcare industry, where I am building Mobile application and retrieval-augmented generation (RAG) systems I use Node.js and Express.js to build backend services and React Native for frontend development.

Project Overview and Learning Objectives

This mini-project allow user to enter an amount in one currency (Rupee) and convert it into others like Dollars, Euros and Pounds. The major objective is learning to use FlatList instead of ScrollView for rendering lists. The project emphasizes the use of TypeScript to provide a clear structure for the app's data and uses interface. With this approach it is easy to achieve type safety.

The projects also covers how to manage user interaction through React's useState hook to track the inputValue, resultValue, and targetCurrency

In this project, I have integrate react-native-snackbar library to provide trigger notifications.

Tip: Open the Source code and alongside read this blog which helps you to understand.

The complete source code is available at GitHub

At the end of the project, you will understand

  1. Build reusable components

  2. Managing states and Business logic

  3. FlatList vs ScrollView

  4. Performance optimization using FlatList


Project Setup and Organization

Create dedicated src folder and move the app.tsx into this folder. Create TypeScript interface in index.d.ts.

The interface defines the mandatory properties for currency object used in the app. This ensures that every button or data point created follows a consistent structure

interface Currency {
    name: string;
    value: number;
    flag: string;
    symbol: string;
}

Rather than hard-coding data directly into the UI components, the project uses a constants.ts file. Storing data this way allows the developer to easily add more currencies in the future without modifying the core logic of the app

export const currencyByRupee: Currency[] = [
    {
      name: 'DOLLAR',
      value: 0.012271428,
      flag: '🇺🇸',
      symbol: '$',
    },
    {...},{....}
}

A specific component, CurrencyButton.tsx, is created to handle the rendering of individual currency items

import { View, Text, StyleSheet } from 'react-native'
import React from 'react'
import type { PropsWithChildren } from 'react'

type CurrencyButtonProps=PropsWithChildren<{
    name:string,
    flag:string
}>

const CurrencyButton = (props:CurrencyButtonProps) => {
  return (
    <View>
      <Text>{props.flag}</Text>
      <Text>{props.name}</Text>
    </View>
  )
}

export default CurrencyButton

Building Reusable Components

For the CurrencyButton component

PropsWithChildren ensure the data passed to the component matches specific types. whenever the component is used, it follows a strict interface, preventing errors caused by missing or incorrect data types.

type CurrencyButtonProps=PropsWithChildren<{
    name:string,
    flag:string
}>

const CurrencyButton = (props:CurrencyButtonProps) => {
  return (
    <View>
      <Text>{props.flag}</Text>
      <Text>{props.name}</Text>
    </View>
  )
}

Managing State and Business Logic

The app tracks three main pieces of information using states to notify the system when the UI needs to be updated inputValue, resultValue, targetCurrency. When a user selects a currency from the list, the buttonPressed function is triggered, carrying the data of the selected currency (of type Currency)

The app performs two critical checks to prevent crashes:

  • Empty Check: If the inputValue is empty, a Snackbar notification pops up with the message "Enter a value to convert".

  • Numeric Validation: The string input is converted to a number using parseFloat. If the resulting value is not a valid number (isNaN), a Snackbar displays "Not a valid number to convert"

After the calculation is complete, the state is updated to reflect the changes on the screen. Here I have separated business logic from the UI components.

  const [inputValue,setInputValue]=useState('');
  const [resultValue,setResultValue]=useState('');
  const [targetCurrency,setTargetCurrency]=useState('');

  function buttonPressed(targetValue:Currency){
    if(!inputValue){
      return Snackbar.show({
        text: "Enter a value to convert",
        backgroundColor: "#EA7773",
        textColor: "#000000"
      })
    }
    const inputAmount=parseFloat(inputValue);
    if(!isNaN(inputAmount)){
      const convertedValue=inputAmount*targetValue.value;
      const result=`\({targetValue.symbol} \){convertedValue.toFixed(2)}`;
      setResultValue(result);
      setTargetCurrency(targetValue.name)
    }
    else{
      return Snackbar.show({
        text: "Not a valid number to convert",
        backgroundColor: "#F4BE2C",
        textColor: "#000000"
      })
    }
  }

Implementing FlatList for Performance

FlatList is more performance-optimized because it only renders items currently visible on the screen, consuming less memory.

Props for Efficiency

  1. data: This prop identifies the source of information

  2. keyExtractor: It is important for performance. It provides a unique identifier (like item.name) for every item in the list, allowing React to efficiently track and update only the specific elements that change.

  3. renderItem: This prop defines the UI for each item in the list. It takes an individual item from your data and returns a component, such as a Pressable button or a custom CurrencyButton.

To make the list functional, wrap the rendered items in a Pressable component: The onPress event triggers the buttonPressed function, passing the specific data for that currency (the item) to calculate the conversion.

<FlatList
          numColumns={3}
          data={currencyByRupee}
          keyExtractor={item=>item.name}
          renderItem={({item}) => (
            <Pressable
            style={[
              styles.button, 
              targetCurrency === item.name && styles.selected
            ]}
            onPress={() => buttonPressed(item)}
            >
              <CurrencyButton {...item} />
            </Pressable>
          )}

        />

Connect with me on X and LinkedIn