this.setState is not a function. React Native noobie - react-native

I keep getting the following error: this.setState is undefined with my React Native project. I have never seen this error before in React, but React Native is new to me. I have done some research and there are many people suggesting to either use a constructor and bind(this) or use an arrow function in the onPress property. I have tried both, but neither seem to work. Please also note that my first 2 functions work fine it is the createUser function that is throwing the error. I would appreicate any help, thanks in advance. Here is my original code:
import React, {Component} from 'react';
import {ScrollView, StyleSheet, TextInput, Text, View, Image, Button } from 'react-native';
import firebase from '../firebase.js';
class Auth extends Component {
state = {
username: "",
password: "",
error: ""}
onChangeUsername= (event) => {
this.setState({ username: event.nativeEvent.text})
}
onChangePassword= (event) => {
this.setState({ password: event.nativeEvent.text})
}
createUser = (event) =>{
firebase.auth().createUserWithEmailAndPassword(this.state.username, this.state.password).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
if(errorCode === "auth/invalid-email")
{this.setState({error: 2})}
console.log(error.code);
console.log(error.message);
});
}
render(){
return(
<View style={{width: "100%", height: "100%", backgroundColor: "#eeeeee",flexDirection:"column", alignItems:"center", justifyContent:"center"}}>
<Text>Email</Text>
<TextInput
value={this.state.username}
autoCorrect={false}
onChange={this.onChangeUsername}
style={{width: "80%", height: "10%", backgroundColor: "white", padding: "2%", margin:"2%"}}
placeholder={"Enter Email"}
autoComplete={"off"}
/>
<Text>Password</Text>
<TextInput
value= {this.state.password}
autoCorrect={false}
onChange={this.onChangePassword}
style={{width: "80%", height: "10%", backgroundColor: "white", padding: "2%", margin:"2%"}}
placeholder={"Enter Password"}
secureTextEntry={true}
/>
<Button title="Sign Up" style={{backgroundColor: "blue", padding: "2%", margin:"2%"}} onPress={(e)=>{this.createUser(e)}}></Button>
<Text>{this.state.error}</Text>
<View style={{width: "100%", height:"20%"}}></View>
</View>
);
}
}
export default Auth;
I have tried replacing
state = {
username: "",
password: "",
error: ""}
with
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
error: ""};
this.createUser = this.createUser.bind(this);
}
I have also tried replacing:
<Button title="Sign Up" style={{backgroundColor: "blue", padding: "2%", margin:"2%"}} onPress={this.createUser}></Button>
and
createUser = () =>{
with
<Button title="Sign Up" style={{backgroundColor: "blue", padding: "2%", margin:"2%"}} onPress={(e)=>{this.createUser(e)}}></Button>
and
createUser = (event) =>{
But neither of these have worked.

I think the problem is following setState:
{this.setState({error: 2})}
This is because the line
firebase.auth().createUserWithEmailAndPassword(this.state.username, this.state.password).catch(function(error) {
will change the this context due the use of function()
Change it to an arrow function to keep the this context.
-->
firebase.auth().createUserWithEmailAndPassword(this.state.username, this.state.password).catch((error) => {

Related

TypeError: _ExpoSecureStore.default.getValueWithKeyAsync is not a function

I am trying to use expo-secure-store in my React Native. I am getting the error below:
Possible Unhandled Promise Rejection (id: 2): TypeError: _ExpoSecureStore.default.getValueWithKeyAsync is not a function. (In '_ExpoSecureStore.default.getValueWithKeyAsync(key, options)', '_ExpoSecureStore.default.getValueWithKeyAsync' is undefined)
I tried to look for solutions but couldn't find one.
So I tried to check it using the sample code given in the docs, but the error is still a similar error:
Possible Unhandled Promise Rejection (id: 1): Error: The method or property SecureStore.setItemAsync is not available on android, are you sure you've linked all the native dependencies properly?
Here is the code that I used:
import * as React from 'react';
import { Text, View, StyleSheet, TextInput, Button } from 'react-native';
import * as SecureStore from 'expo-secure-store';
async function save(key, value) {
await SecureStore.setItemAsync(key, value);
}
async function getValueFor(key) {
let result = await SecureStore.getItemAsync(key);
if (result) {
alert("🔐 Here's your value 🔐 \n" + result);
} else {
alert('No values stored under that key.');
}
}
export default function App() {
const [key, onChangeKey] = React.useState('Your key here');
const [value, onChangeValue] = React.useState('Your value here');
return (
<View style={styles.container}>
<Text style={styles.paragraph}>Save an item, and grab it later!</Text>
{}
<TextInput
style={styles.textInput}
clearTextOnFocus
onChangeText={text => onChangeKey(text)}
value={key}
/>
<TextInput
style={styles.textInput}
clearTextOnFocus
onChangeText={text => onChangeValue(text)}
value={value}
/>
{}
<Button
title="Save this key/value pair"
onPress={() => {
save(key, value);
onChangeKey('Your key here');
onChangeValue('Your value here');
}}
/>
<Text style={styles.paragraph}>🔐 Enter your key 🔐</Text>
<TextInput
style={styles.textInput}
onSubmitEditing={event => {
getValueFor(event.nativeEvent.text);
}}
placeholder="Enter the key for the value you want to get"
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: 10,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
marginTop: 34,
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
textInput: {
height: 35,
borderColor: 'gray',
borderWidth: 0.5,
padding: 4,
},
});
Make sure you use the wildcard import to import Secure Store:
import * as SecureStore from "expo-secure-store";
If the error is still persisting, it may be because you are using a custom developer client. You will need to rebuild your dev client in order to be able to use the Secure Store library.

Change a button color when textinput is null, by using onPress

I just started to learn React Native technology, so i try to change some lines in tutorial code. This is a form, which add new title, but I want to change color of button if value === "". I try to find, but mostly examples use classes, in this project I want to use functions
import React, { useState } from 'react'
import { View, StyleSheet, TextInput, Button, Alert } from 'react-native'
export const AddTodo = ({ onSubmit }) => {
const [value, setValue] = useState('')
const pressHandler = () => {
if (value.trim()) {
onSubmit(value)
setValue('')
} else {
}
}
return (
<View style={styles.block}>
<TextInput
style={styles.input}
onChangeText={setValue}
value={value}
disabled
placeholder='Введите название дела...'
autoCorrect={false}
autoCapitalize='none'
/>
<Button title='Добавить' onPress={pressHandler} />
</View>
)
}
const styles = StyleSheet.create({
block: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 15
},
input: {
width: '70%',
padding: 10,
borderStyle: 'solid',
borderBottomWidth: 2,
borderBottomColor: '#3949ab'
},
button: {
color: 'red'
}
})
You use a controlled input field. You store the value in your state and you change it onChange with the input field. Next step is to set a style for your button depending on your current state.
<TextInput
style={[styles.input, value === '' ? styles.red : null]}
onChangeText={setValue}
value={value}
disabled
placeholder='Введите название дела...'
autoCorrect={false}
autoCapitalize='none'
/>
In this case you need to add a style called "red" which changes the button color.
red: {
backgroundColor: 'red'
}
Something like this.
Because your state is updated every time you change the input value, it gets updated onChange. If you want to set it on submit you need to add a isSubmitted boolean (default false ) to your state and set it to true in your pressHandler.
You need to destructure isSubmitted in this example:
style={[styles.input, value === '' && isSubmitted ? styles.red : null]}
You can apply a simple logic as below
<Button
title="Добавить"
onPress={pressHandler}
color={value === null ? 'red' : 'green'}
/>
EDIT
Check below sample which I created according to your requirement
import React, { useState } from 'react';
import { View, StyleSheet, TextInput, Button } from 'react-native';
export default App = () => {
const [value, setValue] = useState('');
const [error, handleError] = useState(false);
const pressHandler = () => {
if (value.trim()) {
setValue('');
} else {
handleError(true);
}
};
const onHandleChange = (text) => {
setValue(text)
handleError(false)
}
return (
<View style={styles.block}>
<TextInput
style={styles.input}
onChangeText={onHandleChange}
value={value}
placeholder="Введите название дела..."
autoCorrect={false}
autoCapitalize="none"
/>
<Button
title="Добавить"
onPress={pressHandler}
color={error ? 'red' : 'green'}
/>
</View>
);
};
const styles = StyleSheet.create({
block: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 15,
},
input: {
width: '70%',
padding: 10,
borderStyle: 'solid',
borderBottomWidth: 2,
borderBottomColor: '#3949ab',
}
});
Hope this helps you. Feel free for doubts.

React Native: Props Warning, invalid prop value

I'm New to react native,
I'm Building a sample app and when entering data to TextInput field I'm Getting the warning.
I tried running it on Android emulator and on my Pocophone f1 device and got the same results.
I'm using VS Code as my IDE.
I'm Developing on Ubuntu 18.04
Can anyone help?
These are screenshots of the app
the data I'm entering.
The Warning I get
This is my Code
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, TextInput, Button} from 'react-native';
//type Props = {};
export default class App extends Component {
state = {
placeName: "",
places: []
}
placeNameChangedHandler = (event) => {
this.setState({
placeName: event
});
}
placeNameSubmitHandler = () => {
if (this.state.placeName === ""){
return;
}
this.setState(prevState => {
return {
places: prevState.places.concat(prevState.placeName)
};
});
};
render() {
const placesOutput = this.state.places.map(place => (
<Text>{place}</Text>
));
return (
<View style={styles.container}>
<View style={styles.inputContainer}>
<TextInput
style={{width: 200, borderColor: "black", borderWidth: 1}}
placeholder="Place Name"
value={this.state.placeName}
onChangeText={this.placeNameChangedHandler}
style={styles.PlaceInput} />
<Button title="Add" style={styles.placeButton} onPress={this.placeNameChangedHandler} />
</View>
<View>
{placesOutput}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 26,
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
inputContainer:{
width: "100%",
flexDirection: "row",
justifyContent: "space-between",
alignItems: 'center'
},
PlaceInput:{
width: "70%"
},
placeButton:{
width: "30%"
}
});
I changed the code as suggested in the answer below and got an error as shown in the screen below
If you were to log "event" in your placeNameChangedHandler function you would see that it is an object not just the string value you're looking for. So you are setting your state to the full event object and then trying to render it on the screen.
You need to destructure the object to get the string value you're looking for.
placeNameChangedHandler = (event) => {
this.setState({
placeName: event.target.value
});
}
I found the issue: on the **onPress event handler I called the wrong function, sorry for the time I wested **

How to add a text input to alert in react native

Can someone help with adding a text input to an alert in react native. Is it possible? I searched and found results that deals with multiple line text input which is not the case with me. Thanks in advance
This is possible. I believe this was only available initially for AlertIOS however it seems to have been intergrated to React Native Alert.
Edit: Although its added to Alert it does not seem to work for Android
Use
import { Alert } from 'react-native';
onButtonPress = () => {
Alert.prompt(
"Enter password",
"Enter your password to claim your $1.5B in lottery winnings",
[
{
text: "Cancel",
onPress: () => console.log("Cancel Pressed"),
style: "cancel"
},
{
text: "OK",
onPress: password => console.log("OK Pressed, password: " + password)
}
],
"secure-text"
);
};
}
More details: https://reactnative.dev/docs/alertios
Use react-native-dialog it works across platform and is simple enough.
There is no way you could add a text input to the Alert component according to the documentation, You will need to create a custom component by yourself in order to achieve that, example: use customise modal or use react-native-simple-dialogs
No way
Just use custom modal or third party library to achieve this...
Here is a spoiler using a custom Modal:
import React, { FC } from 'react'
import { View, TextInput, Modal, GestureResponderEvent } from 'react-native';
import { BoldText, IOSButton } from '..';
import { colors } from '../../constants';
import { customModalStyles, defaultStyles } from '../../styles';
interface Props {
modalVisible: boolean;
// onRequestClose,
textOne: string;
buttonOneTitle: string;
onPressOne: (event: GestureResponderEvent) => void;
value: string,
onChangeText: (text: string) => void;,
placeholder: string
}
const InputModal: FC<Props> = ({
modalVisible,
// onRequestClose,
textOne,
buttonOneTitle,
onPressOne,
value,
onChangeText,
placeholder
}) => {
return (
<Modal
animationType="fade"
transparent={true}
visible={modalVisible}
// onRequestClose={onRequestClose}
>
<View style={customModalStyles.centeredView}>
<View style={customModalStyles.modalView}>
<BoldText
style={customModalStyles.textSize}>{textOne}
</BoldText>
<TextInput
secureTextEntry
autoCapitalize="none"
style={[
defaultStyles.inputStyle,
defaultStyles.textInputShadow,
]}
value={value}
onChangeText={onChangeText}
placeholder={placeholder}
placeholderTextColor={colors.placeHolder}
/>
<IOSButton title={buttonOneTitle}
onPress={onPressOne}
/>
</View>
</View>
</Modal>
)
}
export default InputModal;
And the styles:
import { StyleSheet } from 'react-native';
import { colors } from '../constants';
import styleConstants from './styleConstants';
const customModalStyles = StyleSheet.create({
buttonsContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
},
centeredView: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
marginBottom: 20,
},
modalView: {
justifyContent: 'space-around',
alignItems: 'center',
width: styleConstants.width < 1000 ? 320 : 400,
height: styleConstants.height < 1000 ? 320 : 400,
backgroundColor: colors.primary,
borderRadius: 20,
paddingHorizontal: 15,
paddingTop: 10,
shadowColor: colors.secondary,
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.55,
shadowRadius: 8,
elevation: 20,
},
textSize: {
textAlign: 'center',
fontSize: styleConstants.fontSizeSM,
},
});
export default customModalStyles;
Then one may use it like this:
{modalVisible && (
<InputModal
modalVisible={modalVisible}
textOne={`...`}
buttonOneTitle="..."
onPressOne={async () => {
setModalVisible(false);
validatePasswordEtc()
}}
placeholder="..."
value={password}
onChangeText={handleChangePassword}
/>
)}
If you think for a moment you will find that an alert and a modal are both a kind of pop-up components. And that leads you to create your own pop-up component instead of using ready-made if you don't have it.
return (
<Modal
animationType="slide"
transparent={true}
onBackdropPress={() => console.log('Pressed')}
visible={props.modalVisible}
onRequestClose={ResetValues}>
<View
style={{
position: 'absolute',
bottom: 0,
right: 0,
backgroundColor: '#4D4D4D',
width: (windowWidth * 100) / 100,
height: (windowHeight * 100) / 100,
}}>
!!!!!!!!! your elements here like text,input,buttons and etc....!!!!!
</View>
</Modal>
);

React Native - text disappearing on custom component style change

Getting a strange error when trying to apply conditional styling to a custom component. Whenever the style change should appear the text completely disappears. If I start typing again, the new styling appears but once the style would change again, the text disappears again. If I apply the styling as static, the custom styling works completely fine. I'm not sure what the issue could be. Thanks in advance for the help.
<UserInput
style = {!this.state.isValidEmail ? styles.errorInline : styles.default}
placeholder="Email"
autoCapitalize={'none'}
returnKeyType={'next'}
autoCorrect={false}
onSubmitEditing={() => this.focusNextField('password')}
updateState={(email) => {
let formattedEmail = email.trim();
this.state.initialValidationChecked? this.validate(formattedEmail) : this.setState({formattedEmail})}
}
blurOnSubmit={true}
onBlur2={(event) => this.validate(event.nativeEvent.text.trim())}
/>
errorInline: {
color: 'red',
},
default : {
color: '#777777'
}
export default class UserInput extends Component {
componentDidMount() {
if (this.props.onRef != null) {
this.props.onRef(this)
}
}
onSubmitEditing() {
if(this.props.onSubmitEditing){
this.props.onSubmitEditing();
}
}
focus() {
this.textInput.focus();
}
render() {
return (
<View style={styles.inputWrapper}>
<TextInput
style={[styles.input, this.props.style]}
placeholder={this.props.placeholder}
secureTextEntry={this.props.secureTextEntry}
autoCorrect={this.props.autoCorrect}
autoCapitalize={this.props.autoCapitalize}
returnKeyType={this.props.returnKeyType}
onChangeText={(value) => this.props.updateState(value)}
onEndEditing={(value) => { if(this.props.onBlur2) return this.props.onBlur2(value)}}
ref={input => this.textInput = input}
blurOnSubmit={this.props.blurOnSubmit}
onSubmitEditing={this.onSubmitEditing.bind(this)}
underlineColorAndroid='transparent'
/>
</View>
);
}
}
UserInput.propTypes = {
placeholder: PropTypes.string.isRequired,
secureTextEntry: PropTypes.bool,
autoCorrect: PropTypes.bool,
autoCapitalize: PropTypes.string,
returnKeyType: PropTypes.string,
};
const DEVICE_WIDTH = Dimensions.get('window').width;
const styles = StyleSheet.create({
input: {
width: DEVICE_WIDTH - 70,
height: 40,
marginHorizontal: 20,
marginBottom: 30,
color: '#777777',
borderBottomWidth: 1,
borderBottomColor: '#0099cc'
},
inputWrapper: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
},
});
Styles are given as object (key-value pair).
But looking at your codes in the following line
style = {!this.state.isValidEmail ? styles.errorInline : 'none'}
When this.state.isValidEmail returns true, you're just giving 'none' to the style, which is a syntax error, you should return something like this
style = {!this.state.isValidEmail ? styles.errorInline : {display: 'none'}}