React Native Currency Formatting Done Native Way

Younite-AI
4 min readJun 9, 2018

--

Howdy!

This time we will be walking through custom components and calling native code to achieve currency formatted text that was used in the TicTok task monitor project. I initially used masked text for formatted text, but since there became more currencies I decided to create a component and do the currency formatting in Android/iOS code. So, here are the steps you need to do and code samples for currency formatted text component using a native module. 😎

Let’s start with Android code. First, we need to create the Java module:

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.text.NumberFormat;
import java.util.Currency;
import java.util.Locale;
public class CurrencyFormatterModule extends ReactContextBaseJavaModule { public CurrencyFormatterModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "CurrencyFormatter";
}
@ReactMethod
public void format(double amount, String currencyCode, Callback callback) {
try {
Currency currency = Currency.getInstance(currencyCode);
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.getDefault());
format.setMaximumFractionDigits(currency.getDefaultFractionDigits());
format.setCurrency(currency);
callback.invoke(format.format(amount));
} catch (Exception e) {
callback.invoke("-");
}
}
}

What we have here is the minimum sample of a native module for Android. There are 2 key points to acknowledge. First is the getName() method, this will be the name we expose for JavaScript which we will be covering later. The second one is the format method. All bridge methods return void, so we are forced to use Callback to deliver the formatted text back to Javascript.

Next part is to get our module exposed. For that we need to create our own ReactPackage and construct the module:

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.example.modules.CurrencyFormatterModule;public class MyPackage implements ReactPackage { @Override
public List createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List createNativeModules(
ReactApplicationContext reactContext) {
List modules = new ArrayList<>();
modules.add(new CurrencyFormatterModule(reactContext)); return modules;
}
}

This package is like any other, it creates the modules and view managers for your own native classes. And to include this in the app you simply add it in your Application class:

protected List getPackages() {
return Arrays.asList(
new MainReactPackage(),
new MyPackage());
}

That’s all you need to do in Android code. Let’s go through the equivalent for iOS. Exposing the module is a little bit more direct, so we will be making 2 files.

CurrencyFormatter.h

#import <React/RCTBridgeModule.h>@interface CurrencyFormatter : NSObject 
@end

CurrencyFormatter.m

#import "CurrencyFormatter.h"@implementation CurrencyFormatterRCT_EXPORT_MODULE();RCT_EXPORT_METHOD(format:(NSNumber * __nonnull)amount currencyCode:(NSString * __nonnull)currencyCode callback:(RCTResponseSenderBlock)callback)
{
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[formatter setCurrencyCode:(NSString *) currencyCode];
callback(@[[formatter stringFromNumber:amount]]);
}
@end

And that’s it. Easy right? But wait, we are still missing the Javascript part. Let’s create CurrencyFormatter.js file which will be the key file in our JS code to export the native module:

import { NativeModules } from 'react-native';module.exports = NativeModules.CurrencyFormatter;

Here you can see NativeModules.CurrencyFormatter which is the match for Android module name and iOS interface class name. And to get this all into action, let’s create custom React component for it.

import React from 'react';
import { Text, ViewPropTypes } from 'react-native';
import PropTypes from 'prop-types';
import CurrencyFormatter from '../modules/CurrencyFormatter';
export default class AmountText extends React.Component {
constructor(props) {
super(props);
this.state = {
text: '',
};
this.formatText(props);
}
componentWillReceiveProps(newProps) {
this.formatText(newProps);
}
formatText(props) {
if (props.amount !== undefined && props.currencyCode !== undefined) {
CurrencyFormatter.format(
props.amount, props.currencyCode,
(formattedText) => {
this.setState({ text: formattedText });
},
);
}
}
render() {
return (

{this.state.text}

);
}
}
AmountText.defaultProps = {
amount: undefined,
currencyCode: undefined,
style: {},
};
AmountText.propTypes = {
amount: PropTypes.number,
currencyCode: PropTypes.string,
style: ViewPropTypes.style,
};

And before we go through what’s happening there, here is sample usage:

<AmountText
style={styles.myAmountStyle}
amount={100.50}
currencyCode={'USD'}
/>

We have defined 3 properties which are amount and currencyCode for the amount itself and style for getting that fancy font and color in. Our component will render state ‘text’ which is the formatted text. We are using state here because the formatting function is asynchronous, so for a very brief moment of time, initially, the component will render nothing. If you have hooked the properties with e.g Redux, the AmountText will automatically update the rendered value when any of those properties change.

There we go, we have created our very first custom module and component.

Cheers and happy coding

Go check out TicTok — Productivity Tracker out and leave your feedback! We want to make this app especially for YOU. See you next time.

More About TicTok:

TicTok has been developed by Finlabs as an internal tool for the team to monitor and log the hours worked against tasks. By simply nudging the user through periodic push notifications, and asking them to log the tasks and time they have just been engaged in, results in a “set it and forget it” system allowing our users to continue their workflow uninterrupted log accurate timings that can easily be referred back to as needed.

--

--