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 + '.');
}
}
}
Related
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;
sorry for my English language
I wrote a function for push JSX elemnts in an array and return that:
import * as React from 'react';
import { View, Text } from 'react-native';
import { Button} from 'react-native-paper';
const buttonLoop = () => {
const items = []
for (var i = 1; i <= 2; i++) {
items.push(<Button icon="camera" onPress={() => alert(i/* Problem is here*/)}>Loop {i/* It work true*/}</Button>)
}
return items;
}
as you can see i inside of element work truly, and show 1 for Button1 and show 2 for Button2.
But when i click on button it show "3" for both button, I want show "1" for Button1 and "2" for Button2
in JQuery i had't this problem, why it don't work true and what's solution?
Think of it like this,
When you click the button the i you are referring to is pointing to the one in the loop which has the value 3 so the way to fix this is passing the i as a parameter like below
This happens when using var due to closures, you will have to use the let keyword.
const ButtonLoop = () => {
const items = [];
for (let i = 1; i <= 2; i++) {
items.push(
<Button icon="camera" onPress={() => alert(i)} title={i}>
Loop {i}
</Button>
);
}
return items;
};
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>
I need some buttons that can be pressed at the same time, but currently if you press one, it 'claims' responsiveness and the others can't be pressed anymore. How do I do this?
Got it. You have to use ReactNativeEventEmitter to directly listen to touch events and bypass the Gesture Responder stuff entirely. Below is a decorator class that calls onTouchStart, onTouchEnd and onTouchMove in the wrapped class whenever those touch events are received.
'use strict';
import React, {Component} from 'react-native';
import ReactNativeEventEmitter from 'ReactNativeEventEmitter';
import NodeHandle from 'NodeHandle';
export const multitouchable = BaseComponent => {
return class extends Component {
constructor(props, context) {
super(props, context);
this.comp = null;
this.compId = null;
}
componentDidMount() {
if(this.comp && this.compId){
this.comp.onTouchStart && ReactNativeEventEmitter.putListener(this.compId, 'onTouchStart', e => this.comp.onTouchStart(e));
this.comp.onTouchEnd && ReactNativeEventEmitter.putListener(this.compId, 'onTouchEnd', e => this.comp.onTouchEnd(e));
this.comp.onTouchMove && ReactNativeEventEmitter.putListener(this.compId, 'onTouchMove', e => this.comp.onTouchMove(e));
}
}
componentWillUnmount() {
if(this.comp && this.compId){
this.comp.onTouchStart && ReactNativeEventEmitter.deleteListener(this.compId, 'onTouchStart');
this.comp.onTouchEnd && ReactNativeEventEmitter.deleteListener(this.compId, 'onTouchEnd');
this.comp.onTouchMove && ReactNativeEventEmitter.deleteListener(this.compId, 'onTouchMove');
}
}
render() {
return (
<BaseComponent {...this.props} {...this.state}
ref={c => {
this.comp = c;
const handle = React.findNodeHandle(c);
if(handle)
this.compId = NodeHandle.getRootNodeID(handle);
}}
/>
);
}
};
}
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