I'm trying to deconstruct the style object but it gives me error on the line const { errorTextStyle } = myStyle; saying: Unexpected token (8:8)".
Below is the whole code:
import React, { Component } from 'react';
import { Platform, Dimensions, Text } from 'react-native';
import { Card, CardSection, Button, Input } from './common';
class LoginForm extends Component {
/////////////////////
state = {email: '', password: '', error: ''};
const { errorTextStyle } = myStyle;
///////////////////// methods
onButtonPress(){
const { email, password } = this.state;
firebase.auth().signInWithEmailAndPassword(email,password).
catch(() => {
firebase.auth().createUserWithEmailAndPassword(email,password).
catch(() => {
this.setState({error: 'Authentication Failed.'});
});
});
}
////////////////////// render
render(){
return(
<Card>
<CardSection >
<Input
placeholder="Type here :)"
onChangeText={ email => this.setState({ email }) }
value={ this.state.email }
label={ 'Email: ' }
autoCorrect={false}
/>
</CardSection >
<CardSection >
<Input
placeholder="Type here :)"
onChangeText={ password => this.setState({password}) }
value={this.state.password}
label={'Password: '}
autoCorrect={false}
secureTextEntry
/>
</CardSection >
<Text style={ errorTextStyle }>
{this.state.error}
</Text>
<CardSection>
<Button onPress={this.onButtonPress.bind(this)}>
Login :)
</Button>
</CardSection>
</Card>
);
}
}
const myStyle = {
errorTextStyle: {
fontSize: 20,
alignSelf: 'center',
color: 'red'
}
};
export default LoginForm;
Since the variable is being used inside render, move that code inside that method. You can only declare methods and fields inside the class declaration, expressions must go inside a method. state = ... is working for you because that's a field declaration. Try the following:
render(){
const { errorTextStyle } = myStyle;
...
}
Related
I started to learn react-native and for now I created a few components in order to use signing in my firebase project. I already created a firebase project from firebase console and dealt with lots of errors. Finally I created my App.js as :
import React, {Component} from 'react';
import {View} from 'react-native';
//import firebase from 'firebase';
//import firebase from '#firebase/app';
import * as firebase from 'firebase';
import '#firebase/auth';
import Header from './src/components/common/Header';
import LoginForm from './src/components/LoginForm';
import CardSection from './src/components/common/CardSection';
import Button from './src/components/common/Button';
import Spinner from './src/components/common/Spinner';
class Main extends Component {
state = {loggedIn: null};
componentDidMount() {
if (!firebase.apps.length) {
firebase.initializeApp({
apiKey: 'AIzaSyCuggnPGozfGB9M1elP7yOG5kdH3Xk5BDM',
authDomain: 'digitus-trial.firebaseapp.com',
databaseURL:
'https://digitus-trial-default-rtdb.europe-west1.firebasedatabase.app',
projectId: 'digitus-trial',
storageBucket: 'digitus-trial.appspot.com',
messagingSenderId: '811615820065',
appId: '1:811615820065:web:993900aab9e5927b5a0660',
measurementId: 'G-4KSTW48LX0',
});
} else {
firebase.app();
}
firebase.auth().onAuthStateChanged((user) => {
if (user) {
this.setState({loggedIn: true});
} else {
this.setState({loggedIn: false});
}
});
}
logoutClicked() {
firebase.auth().signOut();
}
renderContent() {
switch (this.state.loggedIn) {
case true:
return (
<CardSection>
<Button onPress={this.logoutClicked.bind(this)}>Logout</Button>
</CardSection>
);
case false:
return <LoginForm />;
default:
return (
<View>
<Spinner size="large" />
</View>
);
}
}
render() {
return (
<View>
<Header headerText="Digitus Trial" />
{this.renderContent()}
</View>
);
}
}
export default Main;
My problem is when I press login button my button fade out instead of showing a indicator. And also I couldn't get any message which I already put console.log flagging. I'm working with Windows 10 and Android emulator. Can you help me out? For further information here is my form file:
import React, {Component} from 'react';
import {TextInput} from 'react-native';
import firebase from '#firebase/app';
import '#firebase/auth';
import Button from './common/Button';
import Card from './common/Card';
import CardSection from './common/CardSection';
import Spinner from './common/Spinner';
class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {email: '', password: '', loading: false};
}
loginClick() {
this.setState({loading: true});
const {email, password} = this.state;
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(this.loginSuccess.bind(this))
.catch(() => {
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(this.loginSuccess.bind(this))
.catch(this.loginFail.bind(this));
});
}
onPressSignIn() {
this.setState({
loading: true,
});
}
renderCurrentState() {
const {inputStyle} = styles;
if (this.state.loading) {
return (
<Card>
<CardSection>
<TextInput
placeholder="Email"
style={inputStyle}
value={this.state.email}
onChangeText={(email) => this.setState({email})}
/>
</CardSection>
<CardSection>
<TextInput
placeholder="Password"
style={inputStyle}
value={this.state.password}
onChangeText={(password) => this.setState({password})}
/>
</CardSection>
<CardSection>
<Spinner size="large" />
</CardSection>
</Card>
);
}
return (
<Card>
<CardSection>
<TextInput
placeholder="Email"
style={inputStyle}
value={this.state.email}
onChangeText={(email) => this.setState({email})}
/>
</CardSection>
<CardSection>
<TextInput
placeholder="Password"
style={inputStyle}
value={this.state.password}
onChangeText={(password) => this.setState({password})}
/>
</CardSection>
<CardSection>
<Button onPress={() => this.onPressSignIn()}>Login</Button>
</CardSection>
</Card>
);
}
render() {
return <Card>{this.renderCurrentState()}</Card>;
}
}
//Android has no shadow property, in order to use in IOS emulator make elevation:1
const styles = {
inputStyle: {
color: '#000',
paddingRight: 5,
paddingLeft: 5,
fontSize: 18,
lineHeight: 23,
flex: 1,
},
};
export default LoginForm;
After several trials, I found that firebase services are too slow. For every login operation, I need to wait 30 secs or so. So my problem was solved.
I've tried multiple implementations, and I can't seem to get the state to not be undefined. I've tried arrow functions, I've tried binding this inside the onChange event, and nothing seems to work. Can somebody take my codebase and give me some insight as to what I'm doing wrong? Thanks!
import React from 'react';
import {View, Image, StyleSheet} from 'react-native';
import {Button, Text, Input} from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
const styles = StyleSheet.create({
heading: {
padding: 20,
},
});
export default class ContactForm extends React.Component
{
constructor(props)
{
super(props);
this.state = {
name: '',
email: '',
}
}
handleName(e)
{
this.setState({name: e.target.value})
console.log(e.target.value);
}
handleEmail(e)
{
}
submit(e)
{
console.log(this.state.name + " " + this.state.email);
}
render()
{
return (
<View style={styles.heading}>
<Text h5>Sign up to receive updates/newsletters!</Text>
<Input placeholder="your name" onChange={this.handleName.bind(this)} />
<Input placeholder="your email" onChange={this.handleEmail.bind(this)} />
<Button title="Submit" onPress={this.submit}/>
</View>
)
}
}
Hi you can do it like this there is no need to bind the arrow function with "this".
export default class ContactForm extends React.Component
{
constructor(props)
{
super(props);
this.state = {
name: '',
email: '',
}
}
handleName=(e)=>
{ console.log(e);
this.setState({name: e})
}
handleEmail=(e)=>
{
this.setState({email: e})
}
submit=()=>
{
console.log(this.state.name + " " + this.state.email);
}
render()
{
return (
<View style={styles.heading}>
<Text h5>Sign up to receive updates/newsletters!</Text>
<Input placeholder="your name" onChangeText ={this.handleName} />
//change onChange to onChangeText
<Input placeholder="your email" onChangeText={this.handleEmail} />
<Button title="Submit" onPress={this.submit}/>
</View>
)
}
}
Question
Thanks to the props could I make a single textInput custom component to handle differents validations ?
Code
Down below you will find the main Login screen, it's really simple and it consists in 2 text inputs.
import React, { PureComponent, } from 'react';
import { View } from 'react-native';
import MkTextInput from '../../components/MkTextInput'
class LoginScreen extends PureComponent {
state = {
username: '',
password: '',
}
textChanged = fieldName => newValue => this.setState({ [fieldName]: newValue });
render() {
const { username } = this.state;
return(
<View>
<MkTextInput placeholderName='Username' usernameValidation value={username} onChangeText={this.textChanged('username')}/>
<MkTextInput placeholderName='Password' passwordValidation value={username} onChangeText={this.textChanged('password')} />
</View>
)
}
}
export default LoginScreen;
Down below here is the MkTextInputComponent
import React, { PureComponent, Fragment } from 'react';
import { Item, Input, Icon } from 'native-base';
import { userValidation, isTooShort } from '../utils/Validations/UserAndPassValidation';
import { passwordValidator } from '../utils/Validations/PasswordValidation';
import { styles } from './styles';
//ricorda di tradurre tutti i path in path assoluti -->leggi la documentazione.
class MkTextInput extends PureComponent {
state = {
data: '',
}
render() {
const { placeholderName,
usernameValidation,
passwordValidation,
emailValidation,
onChangeText,
value,
} = this.props;
const checkedUsername = usernameValidation ? userValidation(value) : false;
const checkedPassword = passwordValidation ? passwordValidator (value) : false;
return (
<Fragment>
<Item style={styles.container}>
<Input placeholder={placeholderName}
onChangeText={onChangeText}
secureTextEntry={checkedUsername? true : false}
style={checkedUsername ? styles.success : styles.failed}
/>
<Icon name={checkedUsername ? 'checkmark-circle' : 'close-circle'}/>
</Item>
</Fragment>
);
}
}
export default MkTextInput;
The plan
my first intention was to set a specified behaviour based on the props that the MkTextInput components will receive: If you have the props "passwordValidation" the component will deal the validation of the string with this line of code, and will ignore the remaining validation.
const checkedPassword = passwordValidation ? passwordValidator (value) : false;
unluckly this way brings me to has several re-rendering of the same component, or to change the style of the password field just only writing in the username field.
There is a way to make things works ?
unluckly this way brings me to has several re-rendering of the same component, or to change the style of the password field just only writing in the username field.
The above statement is a bit confusing. Are you trying to say that when you enter/type in username field your password field changes styles?
Oh and btw your below code has a mistake. I guess the value props of password field should be value={password} instead of value={username}
return(
<View>
<MkTextInput placeholderName='Username' usernameValidation value={username} onChangeText={this.textChanged('username')}/>
<MkTextInput placeholderName='Password' passwordValidation value={password} onChangeText={this.textChanged('password')} />
</View>
)
Maybe if you can give a little more description on what exactly you are stuck at or your code then maybe I would be able to help.
I think that after several tries i got an answer. Here is my solution:
Login component:
import React, { PureComponent, } from 'react';
import { View } from 'react-native';
import MkTextInput from '../../components/MkTextInput'
class LoginScreen extends PureComponent {
state = {
username: '',
password: '',
email: '',
}
textChanged = fieldName => newValue => this.setState({ [fieldName]: newValue });
render() {
const { username, password, email } = this.state;
return(
<View>
<MkTextInput placeholderName='Username' usernameValidation value={username} onChangeText={this.textChanged('username')} />
<MkTextInput placeholderName='Password' passwordValidation value={password} onChangeText={this.textChanged('password')} />
<MkTextInput placeholderName='E-mail' emailValidation value={email} onChangeText={this.textChanged('email')} />
</View>
)
}
}
export default LoginScreen;
And down below you will find the MkTextInput component
import React, { PureComponent } from 'react';
import { Item, Input, Icon } from 'native-base';
import { usernameValidator, passwordValidator, emailValidator } from '../utils/Validations';
import { styles } from './styles';
//ricorda di tradurre tutti i path relativi in path assoluti -->leggi la documentazione.
class MkTextInput extends PureComponent {
state = {
data: '',
}
render() {
const { placeholderName,
usernameValidation,
passwordValidation,
emailValidation,
onChangeText,
value,
} = this.props;
const checkedUsername = usernameValidator(value) ? <Icon name='checkmark-circle'/> : !value || (value !== null && <Icon name='close-circle'/>);
const checkedPassword = passwordValidator(value) ? <Icon name='checkmark-circle' /> : !value || (value !== null && <Icon name='close-circle'/>);
const checkedEmail = emailValidator(value) ? <Icon name='checkmark-circle' /> : !value || (value !== null && <Icon name='close-circle' />);
return (
<Item style={styles.inputContainer}>
<Input placeholder={placeholderName || ''}
onChangeText={onChangeText}
autoCapitalize='none'
secureTextEntry={passwordValidation ? true : false}
/>
{usernameValidation ? checkedUsername : null}
{passwordValidation ? checkedPassword : null}
{emailValidation ? checkedEmail : null}
</Item>
);
}
}
export default MkTextInput;
I want to clear input after my form submission get successful. I don't want to use reset button in this case.
I have passed submitted data to api that is in another file.
Please help.
file forgotPassword.js
import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { forgotPassword } from "../../actions/authActions";
import classnames from "classnames";
class ForgotPassword extends Component {
constructor() {
super();
this.state = {
email:"",
errors: {}
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({
errors: nextProps.errors
});
}
}
onChange = e => {
this.setState({ [e.target.id]: e.target.value });
};
onSubmit = e => {
e.preventDefault();
var emailId = {
email: this.state.email
};
this.props.forgotPassword(emailId, this.props.history);
};
render(){
const { errors } = this.state;
return (
<div className="container">
<div className="row">
<div className="col s8 offset-s2">
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<h4><b>Forgot Password</b></h4>
</div>
<form noValidate onSubmit={this.onSubmit}>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.email}
error={errors.email}
id="email"
type="email"
className={classnames("", {
invalid: errors.email
})}
/>
<label htmlFor="email">Email</label>
<span className="red-text">{errors.email}</span>
</div>
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<button
style={{
width: "150px",
borderRadius: "3px",
letterSpacing: "1.5px",
marginTop: "1rem"
}}
type="submit"
className="btn btn-large waves-effect waves-light hoverable blue accent-3"
>
Submit
</button>
</div>
</form>
</div>
</div>
</div>
);
}
onHandleSubmit(e) {
e.preventDefault();
const email = this.state.email;
this.props.onSearchTermChange(email);
console.log(email);
this.setState({
email: ''
});
}
}
ForgotPassword.propTypes = {
forgotPassword: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth,
errors: state.errors
});
export default connect(
mapStateToProps,
{ forgotPassword }
)(ForgotPassword);
File authaction.js where calling api
import axios from "axios";
import setAuthToken from "../utils/setAuthToken";
import jwt_decode from "jwt-decode";
import { GET_ERRORS, SET_CURRENT_USER, USER_LOADING} from "./types";
export const forgotPassword = (userData, history) => dispatch => {
axios
.post("/api/users/forgotpassword", userData)
.then(res =>
console.log("forgot password",res)
)
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
After successfull result on api I'm unable to clear input in forgot password form component.
Please let me know if any other way to do this task.I'm a newbie in react.
Many thanks for help.
Changing the value of a TextInput component
You can change the context of the input after an onPress event coming from a button.
export default class App extends React.Component {
state = {
text : "Username"
}
render() {
return (
<View style={styles.container}>
// TextInput gets its value from the state.text above.
<TextInput value={this.state.text } style={{borderColor:"black", border:1}}/>
// Button calls the function in onPress when it is pressed, which cleans up the state.text
<Button title="CLEAN" onPress={() => this.setState({text: ""})} />
</View>
);
}
}
I am doing such things in reactjs but when I started learning react-native it is not working can you tell me how to perform such tasks??
import React, {Component} from 'react';
import {Text, View, Form } from 'react-native';
import { FormLabel, FormInput, FormValidationMessage, Button } from 'react-native-elements';
class Header extends Component {
constructor(props){
super(props);
this.state = {
email : '',
password : '',
};
}
inputData = event => {
this.setState({
[event.target.name]:event.target.value
});
}
submitData = event => {
event.preventDefault();
console.log(this.state);
}
render(){
return(
<View>
<Text style= {{fontSize : 40, marginTop : 50, marginLeft : 100, fontWeight : 'bold'}}>
New App!
</Text>
<FormLabel>Email</FormLabel>
<FormInput name='email' type='email' onChange={this.inputData}/>
<FormLabel>Password</FormLabel>
<FormInput name='password' type='password' onChange={this.inputData}/>
<Button title='Submit' onPress={this.submitData} style={{marginTop:20}}/>
</View>
);
}
}
export default Header;
As you can see over here is that when I used onChange the values are not getting assigned.
I know how to use with onChangeText and it's working also, but can you tell me why the above approach is not working and if not then any significant reasons???
You can try this way, use onChangeText instead of onChange
import React, {Component} from 'react';
import {Text, View, Form } from 'react-native';
import { FormLabel, FormInput, FormValidationMessage, Button } from 'react-native-elements';
class Header extends Component {
constructor(props){
super(props);
this.state = {
email : '',
password : '',
};
}
inputData = event => {
this.setState({
[event.target.name]:event.target.value
});
}
inputEmail = text => {
this.setState({
email: text
})
}
inputPassword = text => {
this.setState({
password: text
})
}
submitData = event => {
event.preventDefault();
console.log(this.state);
}
render(){
return(
<View>
<Text style= {{fontSize : 40, marginTop : 50, marginLeft : 100, fontWeight : 'bold'}}>
New App!
</Text>
<FormLabel>Email</FormLabel>
<FormInput value={this.state.email} name='email' type='email' onChangeText={this.inputEmail}/>
<FormLabel>Password</FormLabel>
<FormInput value={this.state.password} name='password' type='password' onChangeText={this.inputPassword}/>
<Button title='Submit' onPress={this.submitData} style={{marginTop:20}}/>
</View>
);
}
}
export default Header;