commas in Decimals using <Text> - react-native

I have a value which is in a Holder which is supposed to show currency and it shows the currency directly from the REST API, fine and good , but rather than show the value like this
123,456,789.00
It shows like this 123456789.00 I have been trying to format it to no avail. Is there a way to do this in React Native? The holder is looking like this
{this.state.balance}
Searched the internet and could not come up with something good at this point.

Use toLocaleString() to add those commas.
Sample Example:
let num = 123456789.00
console.log(num.toLocaleString())
Full Working Example: Expo Snack
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
let num = 123456789.1;
export default function App() {
const toCommaConvertion = (num) => {
num += 0.001;
let str = [...num.toLocaleString()];
str.pop();
return str.join('');
};
return (
<View style={styles.container}>
<Text style={styles.paragraph}>{toCommaConvertion(num)}</Text>
</View>
);
}

You should convert the number to comma seperated formate
class BalanceExample extends Component {
constructor(props) {
super(props);
this.state = {
balance: 123456789,
};
}
numberWithCommas = (x) => x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
render() {
return (
<Text>{this.numberWithCommas(this.state.balance)}</Text>
);
}
}
export default BalanceExample;

Related

React Native / Expo custom font: German umlauts out of bounds

I've added a custom font (FS Me as an OTF file) to a React Native / Expo app using useFonts from expo-font. Unfortunately, I'm running into an issue where German umlauts (ä, ö, ü) are not visible due to the viewbox of the Text element being too small. For example, take this text: Über uns.
In the app, this simply renders as Uber uns because the two dots above the "U" are out of the Text boundary. When I increase the line height to 1.4x the font size, the umlauts show. However, this a) adds some sort of padding on the bottom of the text and b) it's obviously not a very good solution to increase the line height everywhere. Increasing it on a case-to-case basis isn't a viable solution either.
I'm using a custom Text component which sets a default font like this:
import React from 'react';
import {
TextProps,
Text as RNText, // eslint-disable-line no-restricted-imports
StyleSheet,
StyleProp,
} from 'react-native';
// Animated.createAnimatedComponent requires a class component
// eslint-disable-next-line react/prefer-stateless-function
class Text extends React.Component<TextProps> {
render() {
const { children, style } = this.props;
let styles = style;
let objStyle: StyleProp<any> = {};
if (Array.isArray(style)) objStyle = StyleSheet.flatten(style);
else if (style) objStyle = { ...(style as object) };
if (!objStyle.fontFamily || objStyle.fontFamily === 'FS_Me') {
objStyle.fontFamily = 'FS_Me_400_Regular';
if (objStyle.fontWeight === 'bold' || objStyle.fontWeight === '700') {
objStyle.fontFamily = 'FS_Me_700_Bold';
objStyle.fontWeight = undefined;
}
if (objStyle.fontWeight === 'light' || objStyle.fontWeight === '300') {
objStyle.fontFamily = 'FS_Me_300_Light';
if (objStyle.fontStyle === 'italic') {
objStyle.fontFamily = 'FS_Me_300_Light_Italic';
}
objStyle.fontWeight = undefined;
}
objStyle.backgroundColor = 'red';
styles = objStyle;
}
return (
<RNText allowFontScaling={false} {...this.props} style={styles}>
{children}
</RNText>
);
}
}
export default Text;
However, this also happens when I'm using the core RN Text component and only change the font family.
Does anyone have an idea why this happens?

React-Native HighCharts Boost Module Usage

I have a data set of four series each with 250000 points so approximately one million in total. I am creating an app with React Native. I tried using minimal HighCharts Wrapper but couldn't make the boost module work. Here is my App.js:
import React from 'react';
import { StyleSheet, View } from 'react-native';
import HighchartsReactNative from '#highcharts/highcharts-react-native'
const modules = ['boost']
export default class App extends React.Component {
constructor(props) {
super(props);
let chartSeries = []
for(let i = 0; i < 4 ; i ++){
let series = {data:[]};
for(let i= 0; i < 2500; i++){
let point = [i+1,Math.floor(220-Math.random(0,120)*10)]
series.data.push(point)
}
chartSeries.push(series);
}
this.state = {
chartOptions: {
boost:{
enabled:true,
seriesThreshold:2000
},
chart:{
zoomType:'xy'
},
series: chartSeries
}
};
}
render() {
return (
<View style={styles.container}>
<HighchartsReactNative
styles={styles.container}
options={this.state.chartOptions}
modules={modules}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
justifyContent: 'center',
flex: 1
}
});
It is really simple and it renders eventually but it takes too much time. Boost module doesn't seem to work correctly. Is my usage wrong here?
It does not work correctly, because you set the boost.seriesThreshold equal to 2000 what means that the chart does not switch into the boost module until it has got at least 2000 series.
I think you had intention to set the plotOptions.series.boostThreshold to configure the boost so that it will turn on when certain series has 2000 points, didn't you?
In sum, you just need to set the mentioned seriesThreshold to 1, remove the boost: true (as it is redundant, and true by default), and then set the plotOptions.series.boostThreshold parameter equal to 2000.
API References:
https://api.highcharts.com/highcharts/boost.seriesThreshold
https://api.highcharts.com/highcharts/plotOptions.series.boostThreshold

Console logs only show up once in React Native

I'm trying to get the hang of react native with a very simple app which will log how many times I press a button. Here's my code and my output.
Code:
import React from 'react';
import { View, Text, Button} from 'react-native';
let numOfTimesPressed1 = 0;
let numOfTimesPressed2 = 0;
function printTimesPressed(num) {
if (num == 1) {
numOfTimesPressed1 += 1;
console.log("Log In Button was pressed " + numOfTimesPressed1 + ".");
} else {
numOfTimesPressed2 += 1;
console.log("Log In Button was pressed " + numOfTimesPressed2 + ".");
}
}
class HomeScreen extends React.Component {
render() {
return (
<View>
<Text>Page Master</Text>
<Button
title="Log In"
onPress={printTimesPressed(1)}
>
</Button>
<Button
title="Sign Up"
onPress={printTimesPressed(2)}
>
</Button>
</View>
);
}
}
export default HomeScreen;
Here's my output after I've hit both buttons multiple times:
LOG Running "PageMaster" with {"rootTag":1}
LOG Log In Button was pressed 1.
LOG Log In Button was pressed 1.
Why won't it update?
onPress expects a function to be passed. Your code passes not a function but a result of calling printTimesPressed(1), which is undefined
onPress={printTimesPressed(1)} // wrong: printTimesPressed(1) is not a function but a code that returns nothing
What you want is this
onPress={() => printTimesPressed(1)} // () => printTimesPressed(1) is a function
onPress={function() { printTimesPressed(1) }} // same thing
now onPress receives anonymous arrow function that will, when executed (when button is pressed), call printTimesPressed with respective argument
This happens because functions, on which React is based, are stateless. This is a specialty of functional programming. That means, functions cannot count, and will always act exactly the same when passing the exact same param. You will have to save your number elsewhere (e.g. in a state) to count how often a function is called. Here, you can find an example of a React Counter Button: https://wsvincent.com/react-counter/
First of all,
Please declare the variables and functions in class and try to use latest ECMAScript (ES).
here is the updated code according to standards, the main issue was the onPress handling, as you are trying using an older ES version it was causing issues and lastly in case of one class export that class directly
import React from 'react';
import { View, Text, Button } from 'react-native';
export default class HomeScreen extends React.Component {
numOfTimesPressed1 = 0;
numOfTimesPressed2 = 0;
render() {
return (
<View>
<Button title="Log In" onPress={()=>this.printTimesPressed(1)} />
<Button title="Sign Up" onPress={()=>this.printTimesPressed(2)} />
</View>
);
}
printTimesPressed = (num) => {
if (num == 1) {
this.numOfTimesPressed1 += 1;
console.log('Log In Button was pressed ' + this.numOfTimesPressed1 + '.');
} else if (num == 2) {
this.numOfTimesPressed2 += 1;
console.log('Sign up Button was pressed ' + this.numOfTimesPressed2 + '.');
}
}
}

React Native - How to render text that has breaklines "\n"

I'm trying to find a way to render texts that come from the database with their breaklines "\n".
How can a change the "\n" to the actual breaklines?
You could use this approach.
import React, { Component } from 'react';
import { AppRegistry, ScrollView, Text } from 'react-native';
export default class Main extends Component {
renderText() {
const textFromDB = 'This text\nfrom\ndatabase.'.split('\n');
const rendered = textFromDB.map(x => <Text>{x}</Text>);
return rendered;
}
render() {
return (
<ScrollView>
{this.renderText()}
</ScrollView>
);
}
}
// skip these lines if using Create React Native App
AppRegistry.registerComponent(
'AwesomeProject',
() => Main);
Using Wisnu answer I kinda found out how to do it, because his approach didn't work for me.
function renderTextWithBreakLines(text) {
return text.split(`\n`).map((txt, i) => <Text key={i}>{ txt }{ '\n' }</Text>)
}
And a shorter method would be:
const renderTextWithBreakLines = text => text.split(`\n`).map((txt, i) => <Text key={i}>{ txt }{ '\n' }</Text>);
You can wrap your text inside {} like so
<Text>{`Large Room~\nFully Furnished`}</Text>
Or declare your text as a variable and render like so
const someText = "Large Room\nFully Furnished"
<Text>{someText}</Text>

Can I use multiple or nested elements in the Label of a Picker Item in React Native?

I'm using React Native with NativeBase and would like to make the labels of my Picker more complicated than just one plain string of text.
But is it even possible to pass elements as the label, say multiple child elements wrapped in a single top-level element?
Or do Pickers only support plain text as labels?
As requested by bennygenel, here's a version of what I've tried:
export default class ThingPicker extends React.Component {
render() {
const {
initialThing,
things,
onThingChanged,
} = this.props;
const orderedThings = things.sort();
return (
<Picker
selectedValue={initialThing}
onValueChange={onThingChanged}>
{buildThingItems(orderedThings)}
</Picker>
);
}
}
function buildThingItems(orderedThings) {
let items = orderedThings.map(th => {
const it = th === "BMD" ? (<Text key={th} label={"foo"} value={"bar"}}>Hello</Text>)
: (<Picker.Item key={th} label={th} value={th} />);
return it;
});
}
Yes! It is possible, it just might not look very "right" for React/JSX code. Just create the elements you need and assign them to the label field:
function buildThingItems(orderedThings) {
let items = orderedThings.map(th => {
const it = (<Picker.Item
key={th}
label={currency === "BMD" ? (<Text>Hello</Text>) : th}
value={th} />);
return it;
});
}