How can add a currency prefix to a TextInput in React Native? Here is an example of what I'm trying to achieve:
To give a bit more details - the TextInput should have a default value, for instance £10. I would like the currency sign to always be there.
At some point this value will be sent to a database so it should be converted to an integer.
My code so far (_renderSecondTile section):
import React, {Component} from 'react'
import {
Text,
View,
ListView,
ScrollView,
StyleSheet,
Image,
TouchableHighlight,
TextInput,
} from 'react-native'
class AppView extends Component {
state = {
isPlayerOneButtonActive: false,
isPlayerTwoButtonActive: false,
isThirdTileActive: false,
textInputValue: '£10',
}
activateButton = buttonToActivate => {
const newState = Object.assign(
{},
{
isPlayerOneButtonActive: false,
isPlayerTwoButtonActive: false,
},
{[buttonToActivate]: true},
)
this.setState(newState);
}
showThirdTile = tileToShow => {
this.setState({isThirdTileActive: tileToShow});
}
_renderSecondTile = () => {
if(this.state.isPlayerOneButtonActive || this.state.isPlayerTwoButtonActive) {
return(
<TouchableHighlight>
<View style={[styles.step, styles.stepTwo]}>
<View style={{flex: 1}}>
<Text style={styles.heading}>Enter amount</Text>
<View style={styles.amountInputContainer}>
<TextInput
onKeyPress={() => {this.showThirdTile(true)}}
style={styles.amountInput}
maxLength = {3}
value={this.state.textInputValue}
/>
</View>
</View>
</View>
</TouchableHighlight>
)
}
else{
return null;
}
}
_renderThirdTile = () => {
if(this.state.isSecondTitleActive){
return(
<View style={[styles.step, styles.stepThree]}>
<View style={{flex:1}}>
<Text style={styles.heading}>Third tile</Text>
</View>
</View>
)
}
else{
return null;
}
}
render(){
const {isPlayerOneButtonActive} = this.state
return (
<ScrollView style={styles.container}>
<View style={[styles.step, styles.stepOne]}>
<View style={{flex:1}}>
<Text style={styles.heading}>Pick player</Text>
<View style={styles.pickContainer}>
<TouchableHighlight onPress={() => {this.activateButton('isPlayerOneButtonActive')}}>
<Text>Player One</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => {this.activateButton('isPlayerTwoButtonActive')}}>
<Text>Player One</Text>
</TouchableHighlight>
</View>
</View>
</View>
{this._renderSecondTile()}
{this._renderThirdTile()}
</ScrollView>
)
}
}
Try using this:
class AppView extends Component {
state = {
isPlayerOneButtonActive: false,
isPlayerTwoButtonActive: false,
isThirdTileActive: false,
inputValue: 10,
}
inputChange = (e) => {
this.setState({inputValue: parseInt(e.target.value)});
if(!this.state.isThirdTileActive){
this.showThirdTile(true);
}
}
_renderSecondTile = () => {
if(this.state.isPlayerOneButtonActive || this.state.isPlayerTwoButtonActive) {
return(
<TouchableHighlight>
<View style={[styles.step, styles.stepTwo]}>
<View style={{flex: 1}}>
<Text style={styles.heading}>Enter amount</Text>
<View style={styles.amountInputContainer}>
<TextInput
style={styles.amountInput}
maxLength = {3}
onChange={this.inputChange}
value={"£" + this.state.inputValue}
/>
</View>
</View>
</View>
</TouchableHighlight>
)
}
else{
return null;
}
}
}
Note: I left out anything that I didn't change so my answer would be easier to read.
Here, I changed the textInputValue to inputValue. Now that value is stored as an integer so it is ready to be sent to the database. Whenever that value is changed in the text input field, the state will be updated by inputChange. inputChange will also call showThirdTile if the third tile isn't already active. Finally, the value of the text input will be inputValue concatenated with "£". In my last answer, I added , in the string version of the integer at every thousandth place. Since you have a max length of 3 in the text input field, that isn't necessary any more. If you ever need to increase the max length, I'd use this to convert:
var cashify = function(amountIn){
var amount = parseFloat(amountIn).toFixed(2);
var splitAmount = amount.split(".")[0];
var i = splitAmount.length-4;
while(i>=0){
splitAmount = splitAmount.slice(0,i+1) + "," + splitAmount.slice(i+1);
i=i-3;
}
return "\u00A3" + splitAmount + "." + amount.split(".")[1];
}
I hope that helps!
Related
I'm really confused on how to add (and delete) View and other such components during runtime,
for example in vanilla JavaScript you can use document.querySelector('query-here').appendChild(element);
but how do I achieve the same thing using react native? for example:
<Pressable onPress={()=>{addElement(element)}}>
<View>
//add elements here
</View>
I know how to achieve it directly like this:
<View>
{
[...Array(23)].map((el, index) => {
return(
<View key={index}>
<Text>added new element</Text>
</View>
)});
}
</View>
could someone please point me in the right direction?
#cakelover here how you can add item and remove items based on component's state.
import { Button } from 'react-native';
const [loader, setLoader] = React.useState(false); //donot show loader at initial
const showLoader = isShowLoader => { // based on this function you can add or remove single loader from UI
setLoader(isShowLoader);
}
return (
<View>
{loader && <LoaderComponent/>}
<Button
onPress={() => setLoader(!loader)}
title="Toggle Loader Component"
color="#841584"
/>
</View>
)
If you want to add or remove multiple same components like list you should use arrays of items for that.
I'm not sure but maybe you could try something like this
export default function App() {
const [num, setNum] = useState(() => 0);
const [renderTasks, setRenderTasks] = useState(()=>taskcreate(0));
function taskcreate()
{
let i=num;
setNum(i+1);
return(
<View>
{
[...Array(i)].map((el, index) => {
return (
<View key={index}>
<Text>hello there</Text>
</View>
)
})
}
</View>
)
}
return (
<View style={styles.container}>
<Pressable style={{ height: 50, width: 50, backgroundColor: 'orange' }} onPress={() => { setRenderTasks(taskcreate()) }}></Pressable>
{ renderTasks }
</View>
);
}
Can anyone tell me how to solve these things?
1.if the list is pressed, I'd like to change the background color of the list
beige(#FFF5E7) to white(#FBFBFB)
2.Also, I'd like to change the read value of the Object fales to true with useState
Problem is that if I pressed the list, whole background color of the list will be changed.
index.tsx
import React, { useState } from 'react';
import { Text, View, TouchableOpacity, FlatList } from 'react-native';
import { useNavigation } from '#react-navigation/native';
import { DETAIL } from '../../sample';
import { Object } from './sample';
export default function sample() {
const [state, setState] = useState(Object);
const navigation = useNavigation();
let Element;
const renderItem = ({ item }) => {
const readState = () => {
navigation.navigate(NOTICE_DETAIL);
const readValue = [...state];
let value = { ...readValue[0] };
value.read = true;
readValue[0] = value;
setState(readValue);
};
if (state[0].read) {
Element = (
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: '#FBFBFB' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
);
} else {
Element = (
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: '#FFF5E7' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
);
}
return Element;
};
}
return (
<View style={{ flex: 1 }}>
<FlatList
extraData={Object}
data={Object}
renderItem={renderItem}
/>
</View>
);
}
Object.ts
export const Object = [
{
id: 1,
text: 'testtesttest',
content: 'testtesttest'
read: false
},
{
id: 2,
text: 'testtesttest',
content: 'testtesttest'
read: false
}
id: 3,
text: 'testtesttest',
content: 'testtesttest'
read: false
}
]
We can add inline styles into the component style props along with static styles,
For Example:
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: item.read ? '#FBFBFB' : 'FFF5E7' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
Problem in your readState function and if (state[0].read) {. You always change item with index 0 and then check state[0].read for all elements of your array.
I dont understand how to hide and show Components dependet und a state. I came up with the following code, but i think its wrong, because the UI isnt being update after i press the "login" button. Is there a general way to do this? I also aks myself how to handle changing between "Dialogs". For example i want that when a Button is clicked, that the current Dialog is closed and the target Dialog is renderd. How could i do this?
import React from 'react';
import { ImageBackground, StyleSheet, TouchableOpacity, Text, View, TextInput} from 'react-native';
function WelcomeScreen(props) {
var loginDialog = {
visible: false
};
var signUpDialog = {
visible: false
};
var welcomeDialog = {
visible: true
};
const login = loginDialog.visible ? (
<View style={styles.loginDialog}>
<TextInput style={styles.input}/>
</View>
) : null;
const signup = signUpDialog.visible ? (
<View style={styles.signUpDialog}>
<TextInput style={styles.input}/>
</View>
) : null;
const welcome = welcomeDialog.visible ? (
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={changeState("login")}style={[styles.button, styles.login]}>
<Text style={styles.text}>Log In</Text>
</TouchableOpacity>
<TouchableOpacity onPress={changeState("signup")} style={[styles.button, styles.signUp]}>
<Text style={styles.text}>Sign Up</Text>
</TouchableOpacity>
</View>
) : null;
function changeState(mode){
if(mode === "login"){
console.log("Yes");
welcomeDialog.visible = false;
loginDialog.visible = true;
}else if(mode === "signup"){
welcomeDialog.visible = false;
signUpDialog.visible = true;
}
}
return (
<ImageBackground style={styles.background}
source={require('../assets/welcome_background.jpg')}>
{login}
{signup}
{welcome}
</ImageBackground>
);
}
export default WelcomeScreen;
Seems like you are new to react you should read about state https://reactjs.org/docs/state-and-lifecycle.html.
You should use useState in functional component or setState in class component also I really recomend to use third party library for dialogs/modals.
https://github.com/mmazzarolo/react-native-dialog
https://github.com/react-native-modal/react-native-modal
import React, {useState} from 'react';
import { ImageBackground, StyleSheet, TouchableOpacity, Text, View, TextInput} from 'react-native';
function WelcomeScreen(props) {
const [loginDialog,setLoginDialog] = useState(false);
const [signUpDialog ,setSignUpDialog ] = useState(false);
const [welcomeDialog ,setWelcomeDialog ] = useState(false);
const login = loginDialog ? (
<View style={styles.loginDialog}>
<TextInput style={styles.input}/>
</View>
) : null;
const signup = signUpDialog? (
<View style={styles.signUpDialog}>
<TextInput style={styles.input}/>
</View>
) : null;
const welcome = welcomeDialog? (
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={changeState("login")}style={[styles.button, styles.login]}>
<Text style={styles.text}>Log In</Text>
</TouchableOpacity>
<TouchableOpacity onPress={changeState("signup")} style={[styles.button, styles.signUp]}>
<Text style={styles.text}>Sign Up</Text>
</TouchableOpacity>
</View>
) : null;
const changeState = (mode) => {
if(mode === "login"){
console.log("Yes");
setWelcomeDialog(false);
setLoginDialog(true);
}else if(mode === "signup"){
setWelcomeDialog(false);
setSignUpDialog(true);
}
}
return (
<ImageBackground style={styles.background}
source={require('../assets/welcome_background.jpg')}>
{login}
{signup}
{welcome}
</ImageBackground>
);
}
export default WelcomeScreen;
When I run this inside a function, and click either one of the touchableOpacity I have to save the code for it to check the id number then return the correct outcome
const pressHandler = (id) => {
if (id == 1) {
Pressedinfo = <View>
<Text>one</Text>
</View>
} else if (id = 2) {
Pressedinfo = <View>
<Text>two</Text>
</View>
}
}
in the return (view):
<TouchableOpacity onPress={() => pressHandler(1)}>
<Text style={Styles.Text1}>1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => pressHandler(2)}>
<Text style={Styles.Text1}>2</Text>
</TouchableOpacity>
{Pressedinfo}
You need to use state. Move your react element out of the function and just manipulate the string in state.
In your constructor create a state:
constructor(props){
super(props);
this.state = {textString: ''}
}
const pressHandler = (id) => {
if (id === 1) {
this.setState({textString : 'one'})
}
else if(id === 2) {
this.setState({textString : 'two'})
}
}
For the template:
<TouchableOpacity onPress={() => pressHandler(1)}>
<Text style={Styles.Text1}>1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => pressHandler(2)}>
<Text style={Styles.Text1}>2</Text>
</TouchableOpacity>
<View>
<Text>{this.state.textString}</Text>
</View>
This is how I would try.
import React, { Component, useState } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
const App = () => {
const [Pressedinfo, setPressedInfo] = useState(null)
const pressHandler = (id) => {
if (id == 1) {
setPressedInfo(<View><Text>one</Text></View>)
} else if (id = 2) {
setPressedInfo(<View><Text>two</Text></View>)
}
}
return (
<View>
<TouchableOpacity onPress={() => pressHandler(1)}>
<Text style={Styles.Text1}>1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => pressHandler(2)}>
<Text style={Styles.Text1}>2</Text>
</TouchableOpacity>
{Pressedinfo}
</View>
)
}
use this.state method to change the components without re rendering the page.
I need your help I'm using firebase for my app. I'm trying to get the users ID not the logged users no all users I have. I want to show their (uid) simply like in an alert for each user. Also, I'm showing them in a flatlist and when I set item.uid in an alert it shows (undefined). But, all the other data of the user is shown correctly. This what I did until now:
**
users.js
**
export default class usersList extends React.Component{
state = {
loading: false,
uid: '',
users: [],
items: []
};
componentDidMount() {
let itemsRef = f.database().ref('users').once('value').then(snapshot => {
var data = snapshot.val();
var items = Object.values(data);
this.setState({items});
console.log(snapshot.val())
});
}
renderItem({item}) {
return (
<View key={index} style={{width: '100%', overflow:'hidden', marginBottom: 5, justifyContent:'space-between', borderBottomWidth:1, borderColor: 'grey'}}>
<View>
<View style={{padding:5, width:'100%', flexDirection: 'row', justifyContent: 'space-between'}}>
<Text>{item.email}</Text>
</View>
</View>
</View>
)
}
render() {
return (
<View style={styles.container}>
<ScrollView>
{
this.state.items.length > 0
? <ItemComponent items={this.state.items} navigation={this.props.navigation} />
: <Text>No stores</Text>
}
</ScrollView>
</View>
);
}
}
//ItemComponent.js
export default class ItemComponent extends Component {
static propTypes = {
items: PropTypes.array.isRequired
};
render() {
return (
<View style={styles.itemsList}>
{this.props.items.map((item, index) => {
return (
<View key={index}>
<TouchableOpacity
onPress={ () => alert(item.uid)}>
<Text style={styles.itemtext}>{item.email}</Text>
</TouchableOpacity>
</View>
)
})}
</View>
);
}
}
firebase.database().ref('user').on('value', (datasnapshot) => {
this.setState({
_id: datasnapshot.key
});`
This solution worked for me
<Text style={styles.yourStyleHere}>UID: {auth.currentUser?.uid} </Text>