I can't set State in React Native - android

In this project I want to set the state of the userType using the data that I retrieved from the firebase database. fetching from the firebase is working correctly but I cant set the state of userType from there
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity, TextInput, Image } from 'react-native';
import * as firebase from 'firebase';
export default class Home extends React.Component {
constructor(props){
super(props)
this.state=({
userId:firebase.auth().currentUser.uid,
userType:'f'
})
}
componentDidMount() {
this.readUserData();
};
readUserData=()=> {
userstype= 'users/'+ this.state.userId + '/userType'
firebase.database().ref(userstype).on('value', function (snapshot) {
this.state=({userType:snapshot.val()})
});
alert(this.state.userType)
}
render() {
return (
<View style={styles.container}>
<Text style={styles.titleText}>Taams</Text>
<Text style={styles.edition}>Developer's Edition</Text>
<Text style={styles.titleText}>Home</Text>
<Text>Alpha 0.0.0.1</Text>
</View>

To set the state, please try to do as following instead of this.state=({userType:snapshot.val()}):
this.setState({ userType:snapshot.val() });

Only use this.state ={} in the constructor. Everywhere else it should be.
this.setState({})
so change
firebase.database().ref(userstype).on('value', function (snapshot) {
this.state=({userType:snapshot.val()})
});
to
firebase.database().ref(userstype).on('value', function (snapshot) {
this.setState({userType:snapshot.val()})
});

firebase.database().ref(userstype).on('value', (snapshot) => {
this.setState({userType: snapshot.val()})
});
This might be a context issue. Without binding the anonymous function, you'll lose the original context. Try using an ES6's arrow function and this.setState({})

Related

How to register a new fingerprint in the device?

I am using this library in RN to implement fingerprint scanning react-native-fingerprint-scanner and its working fine with scanning but I would like to implement a function that registers a new fingerprint for this app.
I was absolutely not able to find it anything on the internet related to this.
Here is the code that I have implemented so far:
import React, { Component } from 'react';
import {
Alert,
Image,
Text,
TouchableOpacity,
View,
ViewPropTypes
} from 'react-native';
import FingerprintScanner from 'react-native-fingerprint-scanner';
import PropTypes from 'prop-types';
import ShakingText from './ShakingText.component';
import styles from './FingerprintPopup.component.styles';
class FingerprintPopup extends Component {
constructor(props) {
super(props);
this.state = { errorMessage: undefined };
}
componentDidMount() {
FingerprintScanner
.authenticate({ onAttempt: this.handleAuthenticationAttempted })
.then(() => {
this.props.handlePopupDismissed();
Alert.alert('Fingerprint Authentication', 'Authenticated successfully');
})
.catch((error) => {
this.setState({ errorMessage: error.message });
this.description.shake();
});
}
componentWillUnmount() {
FingerprintScanner.release();
}
handleAuthenticationAttempted = (error) => {
this.setState({ errorMessage: error.message });
this.description.shake();
};
render() {
const { errorMessage } = this.state;
const { style, handlePopupDismissed } = this.props;
return (
<View style={styles.container}>
<View style={[styles.contentContainer, style]}>
<Image
style={styles.logo}
source={require('../pictures/finger_print.png')}
/>
<Text style={styles.heading}>
Fingerprint{'\n'}Authentication
</Text>
<ShakingText
ref={(instance) => { this.description = instance; }}
style={styles.description(!!errorMessage)}>
{errorMessage || 'Scan your fingerprint on the\ndevice scanner to continue'}
</ShakingText>
<TouchableOpacity
style={styles.buttonContainer}
onPress={handlePopupDismissed}
>
<Text style={styles.buttonText}>
BACK TO MAIN
</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
FingerprintPopup.propTypes = {
style: ViewPropTypes.style,
handlePopupDismissed: PropTypes.func.isRequired,
};
export default FingerprintPopup;
EDIT: Or at least I would like to prompt the user to set Fingerprint if they already don't have any finger enrolled in the phone.
I have found out that none of the OS (Android, iOS) will give you access to the keychain that's holding the credentials, for security reasons.
However, I can use the same that's stored in the device's memory by the user to access my app same as other apps if they have the fingerprint feature implemented.
All in all, you cant enrol a new unique fingerprint ONLY for your app!

How to write proper `Keyboard.addListener` in React Native with TypeScript?

I am rewriting a tutorial to TypeScript.
It should console.log after componentDidMount, but it doesn't. It doesn't show any error either.
What am I doing wrong?
Here's my code (minimized it for you):
import React from 'react';
import { View, Text, Animated, Keyboard } from 'react-native';
export class Logo extends React.PureComponent {
constructor(props) {
super(props);
}
componentDidMount() {
console.log(`Hey, I am mounted!`);
this.keyboardDidShowListener = Keyboard.addListener(
`Keyboard will show`,
this.keyboardWillShow
);
this.keyboardDidHideListener = Keyboard.addListener(
`Keyboard will hide`,
this.keyboardWillHide
);
}
componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
keyboardWillShow = () => {
console.log(`Keyboard shows`);
};
keyboardWillHide = () => {
console.log(`Keyboard hides`);
};
render() {
return (
<View>
<Text>
Type the amount right here
</Text>
</View>
);
}
}
Please help.
Tutorial code here: https://github.com/HandlebarLabs/currency-converter-starter/blob/module-3-lesson-10-animation/app/components/Logo/Logo.js
You can import EmitterSubscription interface, which is the return type for Keyboard.addListener(...) from react-native.
Looks like this:
import { Keyboard, EmitterSubscription } from 'react-native';
And then you can add this to your code:
...
export class Logo extends React.PureComponent {
constructor(props) {
super(props);
}
keyboardDidShowListener!: EmitterSubscription;
keyboardDidHideListener!: EmitterSubscription;
...
Note that I added an ! after the property to tell TypeScript that I make sure it gets a value assigned, in this case, in the componentDidMount()
Hope this helps!

How to change value of input react native

Sorry I am new to React Native, and want to know how to change current input value?
As in my case, if I enter a new word directly into input the previous word or the previous value in the value will continue to appear without changing or replacing the new one.
class component:
Keep the value of the input in state of your component which holds this TextInput component.
class ParentComponent extends React.Component {
constructor (props) {
super(props)
this.state = { queryText: '' }
}
handleInputTextChange = (newText) => {
this.setState({ queryText: newText })
}
render () {
return (<View>
<TextInput
onChangeText={this.handleInputTextChange}
value={this.state.queryText}
/>
</View>)
}
}
Notice How I have used onChangeText and handleInputTextChange to handle new values.
Functional Component:
in the functional components, we use hooks. To hold and update text value we use useState
export default () => {
const [text, setText] = useState("");
return <TextView value={text} onChangeText={setText} />;
};
Hello you can use this method :
this.state = {
email: '13119165220',
}
onChangeText={text => this.setState({ email: text })}
In functional components use
export default () => {
const [text,setText] = React.useState("")
return <TextView
value={text}
onChangeText={setText} />
}
TextInput needs value that it is the value that is gonna be shown inside the TextInput.
And to update that value you use onChangeText that is gonna call whatever function you specify every time the text into the TextInput change.
Depending if you are learning React with hooks or without your code will change:
with hooks:
import React,{useState} from 'react'
//others import
function MyTextInput (props){
const [userInput,setUserInput] = useState()
return (
<TextInput
value = {userInput}
onTextChange = {(text) => setUserInput(text)} /> //is always better call another function
) // where you can validate the input
if your using class and coding without hooks, the logic is the same, just change the syntax:
import React,{Component} from 'react'
//other imports
class MyTextInput extends Component{
constructor(props){
super(props)
this.state = {
userInput:''
}
render(){
return (
<TextInput value = {this.state.userInput}
onChangeText = { text => this.setState({userInput:text}) />
)
}
}
Here the links for the docs, where you can find all the props that TextInput receive with explanation: https://reactnative.dev/docs/textinput

react native keep re-render the view every 10 ms when using AsyncStorage

I am newbie in ReactNative. ( I am very familiar with Raw Android)
Yesterday when I was using AsyncStorage ( incorrectly I think) , I met a problem that the View kept re-rendering every n millionseconds.
my code:
import React, { Component} from 'react';
import {Image, Platform, StyleSheet, Text, View, Button} from 'react-native'
import { AsyncStorage } from "react-native"
export default class StorageDemo extends Component{
constructor(props){
super(props)
AsyncStorage.setItem("visitTimes", 100)
this.state = {
isLoaded: false,
visitTimes: 0
}
}
readData = async () => {
try{
const result = await AsyncStorage.getItem("visitTimes")
this.setState(
{
visitTimes: result,
isLoaded: true
}
)
console.info("== loaded, this.state: ")
}catch(error){
console.error(error)
}
}
render() {
this.readData()
if(this.state.isLoaded){
return(
<View>
<Text>Loaded! </Text>
</View>
)
}else{
return(
<View>
<Text>Loading... </Text>
</View>
)
}
}
}
Also I opened a logcat window to check the log, I was shocked by the log: it kept re-rendering the View every 10 ms.
My environment:
Android SDK: 27
Windows
ReactNative 0.55
Device: VIVO Y67A ( Android 6.0 , 4G RAM)
code could be found here: https://github.com/sg552/react_native_lesson_demo/blob/master/screens/StorageDemo.js
I know my code is not correct (using async, await) , so my question is:
How to read from AsyncStorage and render it to page? How to correct my code?
thanks a lot!
Okay, so the problem is that you are calling your func this.readData() inside the render, and that function itself is calling setState which whenever is called, changes the state, which triggers a re-render on the component. So in this situation you have caused an infinite loop in the code, because setState calls render, which in turn calls setState again and you run out of memory.
To fix this quickly, you can remove the function call from your render, and add it to a button, so its only called when you want it to. Something like this:
import React, { Component} from 'react';
import {Image, Platform, StyleSheet, Text, View, Button} from 'react-native'
import { AsyncStorage } from "react-native"
export default class StorageDemo extends Component{
constructor(props){
super(props)
this.state = {
isLoaded: false,
visitTimes: 0
}
}
readData = async () => {
try{
const result = await AsyncStorage.getItem("visitTimes")
this.setState(
{
visitTimes: result,
isLoaded: true
}
)
console.info("== loaded, this.state: ")
}catch(error){
console.error(error)
}
}
render() {
if(this.state.isLoaded){
return(
<View>
<Text>Loaded! {this.state.visitTimes} </Text>
<Button
onPress={() => {
AsyncStorage.setItem("visitTimes", "100")
this.setState({isLoaded: false})
}}
title="Set Storage Item"
/>
</View>
)
}else{
return(
<View>
<Button
onPress={this.readData}
title="Load from async storage"></Button>
</View>
)
}
}
}
Try this and this should give you the value from localStorage!

React Native - Make a component accept a view as prop and display it

I am very much new to React Native.
In my project, I have a requirement that looks like this.
I have a Component called BaseComponent that accepts a View as a prop and display it inside a touchable highlight in its render method.
I am using this BaseComponent in my CustomComponent by passing a view as a prop. This View which is being passed is returned from a function called getView(). But it is showing me a blank screen.
// BaseComponent.js
import React, { Component } from 'react'
import {
View,
TouchableHighlight
} from 'react-native'
export default class BaseComponent extends Component {
render() {
return(
<TouchableHighlight onPress= { this.onPress.bind(this) } >
<View>
{
this.props.contentView
}
</View>
</TouchableHighlight>
);
}
}
--
// CustomComponent.js
import React, { Component } from 'react'
import { Text } from 'react-native'
import BaseComponent from './BaseComponent'
export default class CustomComponent extends Component {
getView() {
return(
<Text> Hello { this.props.name }! </Text>
)
}
render() {
<BaseComponent contentView={ this.getView.bind(this) }>
}
}
i just edit your code like:
// BaseComponent.js
import React, { Component } from 'react';
import { View, TouchableHighlight, Text } from 'react-native';
export default class BaseComponent extends Component {
render() {
return (
<TouchableHighlight onPress={null}>
<View>
<Text> hello </Text>
</View>
</TouchableHighlight>
);
}
}
And ...
// CustomComponent.js
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import BaseComponent from './BaseComponent';
export default class routerFlax extends Component {
getView() {
return <Text> Hello {this.props.name}! </Text>;
}
render() {
return <BaseComponent contentView={this.getView.bind(this)} />;
}
}
in my emulator the code showing like :
The problem is you pass the props null and you don't return component render. So the result is blank.
Edit#1
based on your comment about your problem, i think you just change:
<BaseComponent contentView={this.getView.bind(this)} />;
To
<BaseComponent contentView={this.getView()} />;
in my emulator the code showing like :
I hope my answer helping you.. thanks :)

Categories

Resources