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

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>

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?

commas in Decimals using <Text>

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;

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 + '.');
}
}
}

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;
});
}

move the view up when keyboard as shown in react-native

hai i am trying to move the view up when keyboard as shown using react-native,I followed the #sherlock's comment in (How to auto-slide the window out from behind keyboard when TextInput has focus? i got an error like this
I don't know how to resolve this error, can any one help me how to resolve this, any help much appreciated.
There's a great discussion about this in the react-native github issues
https://github.com/facebook/react-native/issues/3195#issuecomment-147427391
I'd start there, but here are a couple more links you may find useful, one of which is mentioned already in the article you referenced...
[React Tips] Responding to the keyboard with React Native
Andr3wHur5t/react-native-keyboard-spacer
In my library "react-native-form-generator" (https://github.com/MichaelCereda/react-native-form-generator) i did the following.
I created a Keyboard Aware scroll view (partially modified from https://github.com/facebook/react-native/issues/3195#issuecomment-146518331)
the following it's just an excerpt
export class KeyboardAwareScrollView extends React.Component {
constructor (props) {
super(props)
this.state = {
keyboardSpace: 0,
}
this.updateKeyboardSpace = this.updateKeyboardSpace.bind(this)
this.resetKeyboardSpace = this.resetKeyboardSpace.bind(this)
}
updateKeyboardSpace (frames) {
let coordinatesHeight = frames.endCoordinates.height;
const keyboardSpace = (this.props.viewIsInsideTabBar) ? coordinatesHeight - 49 : coordinatesHeight
this.setState({
keyboardSpace: keyboardSpace,
})
}
resetKeyboardSpace () {
this.setState({
keyboardSpace: 0,
})
}
componentDidMount () {
// Keyboard events
DeviceEventEmitter.addListener('keyboardWillShow', this.updateKeyboardSpace)
DeviceEventEmitter.addListener('keyboardWillHide', this.resetKeyboardSpace)
}
componentWillUnmount () {
DeviceEventEmitter.removeAllListeners('keyboardWillShow')
DeviceEventEmitter.removeAllListeners('keyboardWillHide')
}
scrollToFocusedInput (event, reactNode, extraHeight = 69) {
const scrollView = this.refs.keyboardScrollView.getScrollResponder();
setTimeout(() => {
scrollView.scrollResponderScrollNativeHandleToKeyboard(
reactNode, extraHeight, true
)
}, 220)
}
render () {
return (
<ScrollView
ref='keyboardScrollView'
keyboardDismissMode='interactive'
contentInset={{bottom: this.state.keyboardSpace}}
showsVerticalScrollIndicator={true}
style={this.props.style}>
{this.props.children}
</ScrollView>
)
}
Then i use it like any other scrollview
import { KeyboardAwareScrollView } from 'react-native-form-generator'
...
handleFormFocus(event, reactNode){
this.refs.scroll.scrollToFocusedInput(event, reactNode)
}
...
<KeyboardAwareScrollView ref='scroll'>
<Form ref='registrationForm'
onFocus={this.handleFormFocus.bind(this)}
onChange={this.handleFormChange.bind(this)}
label="Personal Information">
........
</Form>
</KeyboardAwareScrollView>
on change my component (Form) will call scrollToFocusedInput in KeyboardAwareScrollView (using the ref).
i suggest to check the code of my library (see the link on top), or simply use it (everything it's already tested and working).
If you have further questions just comment