Firebase custom fields createUserWithEmailAndPassword after creating user its logging out - javascript

import React, { Component } from "react";
import fire from "../config/fire";
import { Form, Button } from "react-bootstrap";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import logo from "./logo.png";
export default class CreateUser extends React.Component {
constructor(props) {
super(props);
this.login = this.login.bind(this);
this.handleChange = this.handleChange.bind(this);
this.state = {
email: "",
pwd: "",
name: "",
phoneNo: "",
address: "",
};
}
login(e) {
const db = fire.firestore();
e.preventDefault();
fire
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.pwd)
// .signInWithEmailAndPassword(this.state.email, this.state.pwd)
.then((u) => {
// console.log(u.user.uid);
return db.collection("createdUsers").doc(u.user.uid).set({
email: this.state.email,
name: this.state.name,
phoneNo: this.state.phoneNo,
address: this.state.address,
});
})
.then(() => {
this.setState({
email: "",
pwd: "",
name: "",
phoneNo: "",
address: "",
});
})
.then(() => {
alert("Successfully Created the user!");
})
.catch((error) => {
alert(error);
});
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
render() {
return (
<Container style={{ margin: 0, padding: 0, maxWidth: 1366 }}>
<Row>
{/* <Col
style={{
backgroundColor: "#EFEFEF",
paddingTop: 250,
height: 700,
}}
> */}
{/* <img src={logo} alt="Logo" width="150px" /> */}
{/* </Col> */}
<Col
// style={{
// backgroundColor: "#ffffff",
// paddingTop: 250,
// height: 700,
// }}
>
<div>
<Form style={{ width: 300, height: 300, margin: "0 auto" }}>
<Form.Group controlId="formBasicEmail">
<Form.Label>Username</Form.Label>
<Form.Control
type="email"
placeholder="Enter your email"
id="email"
name="email"
placeholder="Enter your email address"
onChange={this.handleChange}
value={this.state.email}
required
/>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
placeholder="Password"
id="pwd"
name="pwd"
placeholder="Password"
onChange={this.handleChange}
value={this.state.pwd}
required
/>
</Form.Group>
<Form.Group controlId="formBasicInput1">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
placeholder="Name"
id="name"
name="name"
placeholder="Name"
onChange={this.handleChange}
value={this.state.name}
required
/>
</Form.Group>
<Form.Group controlId="formBasicInput2">
<Form.Label>Phone Number</Form.Label>
<Form.Control
type="text"
placeholder="Phone Number"
id="phoneNo"
name="phoneNo"
onChange={this.handleChange}
value={this.state.phoneNo}
required
/>
</Form.Group>
<Form.Group controlId="formBasicInput3">
<Form.Label>Address</Form.Label>
<Form.Control
type="text"
placeholder="Address"
id="address"
name="address"
onChange={this.handleChange}
value={this.state.address}
required
/>
</Form.Group>
<Button variant="primary" type="submit" onClick={this.login}>
Create User
</Button>
</Form>
</div>
</Col>
</Row>
</Container>
);
}
}
In the above code, I'm creating a user and with some custom fields. And I'm already logging into the app from some other component(using signInWithEmailAndPassword) and then inside app, I'm creating users, But, after clicking "create user" button, it's making me log out and if I again log in with the credentials from which I used to log in always, after logging in its showing me the alert message, and then it's creating user and storing the values in firestore collection.
Now in this, It should create user and store the custom values in firestore collection. And then it should make fields empty and then it should show alert message. But it should not make me log out.
Please help me out with this...

Related

I am trying to get the value of a form input using React-Bootstrap

My form is not capturing the inputs. My code looks correct to me after following this thread. This is what I have:
import { NavLink, useNavigate } from "react-router-dom";
import { useState } from 'react';
import { Card, Row, Col, Container, Form, Button} from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
function Signup({setUser}) {
const navigate = useNavigate();
const [ formData, setFormData ] = useState({
username: '',
email: '',
password: ''
})
const [ errors, setErrors ] = useState([])
function handleChange(e) {
const key = e.target.name;
const value = e.target.value;
setFormData({...formData, [key]: value})
}
function handleSubmit(e) {
e.preventDefault();
fetch('/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
})
.then(res => {
if (res.ok) {
res.json().then(setUser)
navigate("/")
setFormData({
email: '',
password: ''
})
} else {
res.json().then(errorResponse => setErrors(errorResponse.errors))
}
})
}
return (
<div className="App-header">
<div>
<h1>Sign Up</h1>
<Form onSubmit={handleSubmit} id="myForm" >
<Form.Group className="mb-3" controlId="formUsername" >
<Form.Label> Username</Form.Label>
<Form.Control type="text" placeholder="Username" onChange={handleChange}/>
</Form.Group>
<Form.Group className="mb-3" controlId=" formEmail">
<Form.Label> Email Address</Form.Label>
<Form.Control type="email" placeholder="Enter email" onChange={handleChange}/>
</Form.Group>
<Form.Group className="mb-3" controlId="formPassword">
<Form.Label> Password</Form.Label>
<Form.Control type="password" placeholder="Enter password" onChange={handleChange}/>
{errors.length > 0 ? <div className="error-container">{errors.map(error => <p className="error" key={error}>{error}</p>)}</div> : <div></div>}
</Form.Group>
<Button variant="success" type="submit" form="myForm">
Submit
</Button>
</Form>
</div>
</div>
);
}
export default Signup;
I get error messages saying the Username/ Email / Password can't be blank. What is interesting to me is that I have the same code, but not using bootstrap, and it works. Appreciate the help.
I think you should have name attribute for each Form.Control. For example,
<Form.Control name="username" type="text" placeholder="Username" onChange={handleChange}/>
<Form.Control name="email" type="email" placeholder="Enter email" onChange={handleChange}/>
<Form.Control name="password" type="password" placeholder="Enter password" onChange={handleChange}/>

Unhandled Rejection (TypeError): register is not a function

Getting this error for register when onSubmit is initiated. I've been trying to debug it for the last couple days, and even had a second set of eyes try as well with no luck.
The solutions that i've tried so far include checking to see if register was exported correctly, reviewing if the destructuring was handled correctly, and if I was calling the function with proper syntax. Each of these seem to check out, which leads me to being stumped and not sure how to resolve the issue.
Console error:
Uncaught (in promise) TypeError: register is not a function
onSubmit Register.js:30
onSubmit Register.js:39
Setting up register:
import axios from 'axios'
import { setAlert } from './alert'
import {
REGISTER_SUCCESS,
REGISTER_FAIL,
} from './types'
// Register user
export const register = ({ name, email, password }) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
}
const body = JSON.stringify({ name, email, password })
try {
const res = await axios.post('/u', body, config)
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
})
// dispatch(loadUser())
} catch (err) {
const errors = err.response.data.errors
if (errors) {
errors.forEach(error => dispatch(setAlert(error.msg, 'danger')))
}
dispatch({
type: REGISTER_FAIL
})
}
}
Register form:
import { connect } from 'react-redux'
import axios from 'axios'
import { Container, Form, Col, Row, Button } from 'react-bootstrap'
import { Link } from 'react-router-dom'
import { setAlert } from '../actions/alert'
import { register } from '../actions/auth'
import PropTypes from 'prop-types'
export const Register = ({ setAlert, register }) => {
const [ formData, setFormData ] = useState({
firstName: '',
lastName: '',
username: '',
email: '',
password: '',
password2: ''
})
const { firstName, lastName, email, username, password, password2 } = formData
const onChange = e => setFormData({ ...formData, [ e.target.name ]: e.target.value })
const onSubmit = async e => {
e.preventDefault()
if (password !== password2) {
setAlert('Passwords do not match', 'danger')
} else {
register({ firstName, lastName, username, email, password })
}
}
return (
<>
<h4 className="text-center my-3">Create account</h4>
<Container className="d-flex mx-auto justify-content-center bottomPaddingGap">
<Row className="d-flex flex-column">
<Form onSubmit={e => onSubmit(e)}>
<Row>
<Col md="auto">
<Form.Group className="mt-3">
<Form.Label>First name</Form.Label>
<Form.Control
required
type="text"
name="firstName"
placeholder="John"
value={firstName}
onChange={e => onChange(e)}
/>
</Form.Group>
</Col>
<Col md="auto">
<Form.Group className="mt-3">
<Form.Label>Last name</Form.Label>
<Form.Control
required
type="text"
name="lastName"
placeholder="Doe"
value={lastName}
onChange={e => onChange(e)}
/>
</Form.Group>
</Col>
</Row>
<Row>
<Col md="auto">
<Form.Group className="mt-3">
<Form.Label>Email</Form.Label>
<Form.Control
required
type="email"
name="email"
value={email}
onChange={e => onChange(e)}
/>
</Form.Group>
</Col>
<Col md="auto">
<Form.Group className="mt-3">
<Form.Label>Username</Form.Label>
<Form.Control
required
type="text"
name="username"
placeholder="#"
value={username}
onChange={e => onChange(e)}
/>
</Form.Group>
</Col>
</Row>
<Row>
<Col md="auto">
<Form.Group className="mt-3">
<Form.Label>Password</Form.Label>
<Form.Control
required
type="password"
name="password"
minLength="6"
value={password}
onChange={e => onChange(e)}
/>
</Form.Group>
</Col>
<Col md="auto">
<Form.Group className="mt-3">
<Form.Label>Confirm password</Form.Label>
<Form.Control
required
type="password"
name="password2"
minLength="6"
value={password2}
onChange={e => onChange(e)}
/>
</Form.Group>
</Col>
</Row>
<Form.Group className="mt-3">
<Form.Control
type="submit"
value="Create your account"
className="btn btn-primary"
/>
</Form.Group>
</Form>
<div className="text-center mt-3 border-top">
<p className="text-muted pt-3 mb-1">Already have an account?</p>
<Link to="/login" className="noDecor">
<div className="d-grid gap-2">
<Button variant="secondary">Log In</Button>
</div>
</Link>
</div>
</Row>
</Container>
</>
)
}
Register.propTypes = {
setAlert: PropTypes.func.isRequired,
register: PropTypes.func.isRequired
}
export default connect(null, { setAlert, register })(Register)```
[1]: https://i.stack.imgur.com/5bGce.png

this.setState not updating

I'm trying to take the inputs using a form and update the state when the checkbox is clicked but for some reason, the state doesn't update. It doesn't throw any error. I searched on google for answers but none of them were plausible.
My code:
class PatientForm extends React.Component{
constructor(){
super();
this.state={
patientName: "",
age: null,
sex: "",
email: "",
phoneNo: null
}
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit = (event) => {
console.log(this.state);
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
alert(this.state.patientName);
console.log(this.state);
}
render(){
return (
<div className="container-fluid">
<Jumbotron>
<h3 className="display-5">Enter Patient info</h3>
<Form>
<Form.Text className="text-muted">
We'll never share your details with anyone else.
</Form.Text>
<Form.Row>
<Col>
<Form.Control name="patientName" type="text" placeholder="Patient name" required/>
</Col>
<Col>
<Form.Control name="age" type="number" placeholder="Patient Age" required/>
</Col>
<Col>
<Form.Control name="sex" type="text" placeholder="Patient Sex" required/>
</Col>
</Form.Row>
<br />
<Form.Group>
<Form.Control name="email" type="email" placeholder="Enter email" required/>
</Form.Group>
<Form.Group>
<Form.Control name="phoneNo" type="number" placeholder="Phone number" required/>
</Form.Group>
<Form.File />
<Form.Label>Patient's Eth Address</Form.Label>
<Form.Text className="text-muted">
################
</Form.Text>
<Form.Group >
<Form.Check
type="checkbox"
label="Tick if the entered info is correct"
onClick = {this.handleSubmit}
/>
</Form.Group>
<Button variant="primary" type="submit" onClick={ () => console.log(this.state)}>
Submit
</Button>
</Form>
<p>{this.state.patientName}</p>
</Jumbotron>
</div>
)
}
}
export default PatientForm;
Here the handleSubmit function is revoked when the checkbox is clicked.
You need to attach the handleSubmit function to onChange event of every <Form.Control /> you want to use to update the state properties.
Read the "Handling Multiple Inputs" documentation page for more insights.
Here is how you should write you <PatientForm /> (I renamed handleSubmit to handleChange and provide new implementation of handleSumbit):
class PatientForm extends React.Component {
constructor() {
super();
this.state = {
patientName: "",
age: null,
sex: "",
email: "",
phoneNo: null
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(event) {
// e.g.: send to remote API
event.preventDefault();
console.log("state", this.state);
console.log("data sent to remote API");
}
render() {
return (
<div className="container-fluid">
<Jumbotron>
<h3 className="display-5">Enter Patient info</h3>
<Form>
<Form.Text className="text-muted">
We'll never share your details with anyone else.
</Form.Text>
<Form.Row>
<Col>
<Form.Control
name="patientName"
type="text"
placeholder="Patient name"
onChange={this.handleChange}
required
/>
</Col>
<Col>
<Form.Control
name="age"
type="number"
placeholder="Patient Age"
onChange={this.handleChange}
required
/>
</Col>
<Col>
<Form.Control
name="sex"
type="text"
placeholder="Patient Sex"
onChange={this.handleChange}
required
/>
</Col>
</Form.Row>
<br />
<Form.Group>
<Form.Control
name="email"
type="email"
placeholder="Enter email"
onChange={this.handleChange}
required
/>
</Form.Group>
<Form.Group>
<Form.Control
name="phoneNo"
type="number"
placeholder="Phone number"
onChange={this.handleChange}
required
/>
</Form.Group>
<Form.File />
<Form.Label>Patient's Eth Address</Form.Label>
<Form.Text className="text-muted">################</Form.Text>
<Form.Group>
<Form.Check
type="checkbox"
label="Tick if the entered info is correct"
/>
</Form.Group>
<Button variant="primary" type="submit" onClick={this.handleSubmit}>
Submit
</Button>
</Form>
<p>{this.state.patientName}</p>
</Jumbotron>
</div>
);
}
}

How do I appropriately handle field change events in React using a custom hook?

I am currently building a simple signup form page to build my knowledge of React Web Apps. I have a number of different types of form elements. I am running into the following error when I use my custom hook to handle changes in any of the form fields that are not simple text fields.
TypeError: Cannot read property 'name' of undefined
(anonymous function)
C:/Users/paris/Desktop/covidsocial/frontend/src/libs/hooksLib.js:11
function(event) {
9 | setValues({
10 | ...fields,
> 11 | [event.target.name]: event.target.value
| ^ 12 | });
13 | }
14 | ];
The above error message occurs anytime i select a country from the region and country selector drop-downs or the date picker. I have tried using both name and control-id elements as the ids but I still get the same error message as above. I think the issue is with how I am setting my values, but I am very new to React and am having trouble pinning down exactly whats going on. Any help would be greatly appreciated!
Here is the relevant code for my Signup.js class as well as the custom react hook
hookslib.js
import { useState } from "react";
export function useFormFields(initialState) {
const [fields, setValues] = useState(initialState);
return [
fields,
function(event) {
setValues({
...fields,
[event.target.name]: event.target.value
});
}
];
}
Signup.js
export default function Signup() {
const [fields, handleFieldChange] = useFormFields({
email: "",
password: "",
confirmPassword: "",
confirmationCode: "",
gender: "",
onList: false,
dateOfBirth: "",
mailingAddressLine1: "",
mailingAddressLine2: "",
mailingAddressCity: "",
mailingAddressState: "",
mailingAddressZip: "",
billingAddressLine1: "",
billingAddressLine2: "",
billingAddressCity: "",
billingAddressState: "",
billingAddressZip: "",
useShippingAsBilling: false,
});
const history = useHistory();
const [newUser, setNewUser] = useState(null);
const { userHasAuthenticated } = useAppContext();
const [isLoading, setIsLoading] = useState(false);
function validateForm() {
return (
fields.email.length > 0 &&
fields.password.length > 0 &&
fields.password === fields.confirmPassword
);
}
function validateConfirmationForm() {
return fields.confirmationCode.length > 0;
}
async function handleSubmit(event) {
event.preventDefault();
setIsLoading(true);
try {
const newUser = await Auth.signUp({
username: fields.email,
password: fields.password,
confirmPassword: fields.confirmPassword,
gender: fields.gender,
firstName: fields.firstName,
lastName: fields.lastName,
onList: fields.onList,
dateOfBirth: fields.dateOfBirth,
mailingAddressLine1: fields.mailingAddressLine1,
mailingAddressLine2: fields.mailingAddressLine2,
mailingAddressCity: fields.mailingAddressCity,
mailingAddressState: fields.mailingAddressState,
mailingAddressZip: fields.mailingAddressZip,
mailingAddressCountry: fields.mailingAddressCountry,
billingAddressCountry: fields.billingAddressCountry,
billingAddressLine1: fields.billingAddressLine1,
billingAddressLine2: fields.billingAddressLine2,
billingAddressCity: fields.billingAddressCity,
billingAddressState: fields.billingAddressState,
billingAddressZip: fields.billingAddressZip,
});
setIsLoading(false);
setNewUser(newUser);
} catch (e) {
onError(e);
setIsLoading(false);
}
}
async function handleConfirmationSubmit(event) {
event.preventDefault();
setIsLoading(true);
try {
await Auth.confirmSignUp(fields.email, fields.confirmationCode);
await Auth.signIn(fields.email, fields.password);
userHasAuthenticated(true);
history.push("/");
} catch (e) {
onError(e);
setIsLoading(false);
}
}
function renderConfirmationForm() {
return (
<form onSubmit={handleConfirmationSubmit}>
<FormGroup controlId="confirmationCode" bsSize="large">
<ControlLabel>Confirmation Code</ControlLabel>
<FormControl
autoFocus
type="tel"
onChange={handleFieldChange}
value={fields.confirmationCode}
/>
<HelpBlock>Please check your email for the code.</HelpBlock>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isLoading}
disabled={!validateConfirmationForm()}
>
Verify
</LoaderButton>
</form>
);
}
function renderForm() {
return (
<form onSubmit={handleSubmit}>
<FormGroup controlId="email" bsSize="large">
<ControlLabel>Email</ControlLabel>
<FormControl
autoFocus
name = "email"
type="email"
value={fields.email}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="password" bsSize="large">
<ControlLabel>Password</ControlLabel>
<FormControl
type="password"
name = "password"
value={fields.password}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="confirmPassword" bsSize="large">
<ControlLabel>Confirm Password</ControlLabel>
<FormControl
type="password"
name = "confirmPassword"
onChange={handleFieldChange}
value={fields.confirmPassword}
/>
</FormGroup>
<FormGroup controlId="mailingAddressLine1" bsSize="large">
<ControlLabel>Mailing Address Line 1</ControlLabel>
<FormControl
type="text"
name = "mailingAddressLine1"
onChange={handleFieldChange}
value={fields.mailingAddressLine1}
/>
</FormGroup>
<FormGroup controlId="mailingAddressLine2" bsSize="large">
<ControlLabel>Mailing Address Line 2</ControlLabel>
<FormControl
type="text"
name = "mailingAddressLine2"
onChange={handleFieldChange}
value={fields.mailingAddressLine2}
/>
</FormGroup>
<FormGroup controlId="mailingAddressCountry" bsSize="large">
<ControlLabel>Country</ControlLabel>
<CountryDropdown
name = "mailingAddressCountry"
country={fields.mailingAddressCountry}
value={fields.mailingAddressCountry}
onChange={handleFieldChange} />
</FormGroup>
<FormGroup controlId="mailingAddressRegion" bsSize="large">
<ControlLabel>State</ControlLabel>
<RegionDropdown
//country={country}
name="mailingAddressRegion"
country={fields.mailingAddressCountry}
value={fields.mailingAddressState}
onChange={handleFieldChange} />
</FormGroup>
<FormGroup controlId="city" bsSize="large">
<ControlLabel>City</ControlLabel>
<FormControl
type="text"
name="city"
onChange={handleFieldChange}
value={fields.mailingAddressCity}
/>
</FormGroup>
<FormGroup controlId="zipCode" bsSize="large">
<ControlLabel>Zip Code</ControlLabel>
<FormControl
type="text"
name="zipCode"
onChange={handleFieldChange}
value={fields.mailingAddressZip}
/>
</FormGroup>
<FormGroup controlId="useShippingAsBilling" bsSize="large">
<label>
Use Shipping As Billing:
<input
name = "useShippingAsBilling"
type="checkbox"
id="useShippingasBilling"
value={fields.useShippingAsBilling}
checked={fields.useShippingAsBilling === true}
onChange={handleFieldChange} />
</label>
</FormGroup>
<br />
<FormGroup controlId="billingAddressLine1" bsSize="large">
<ControlLabel>Billing Address Line 1</ControlLabel>
<FormControl
name ="billingAddressLine1"
type="text"
value={fields.billingAddressLine1}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="billingAddressLine2" bsSize="large">
<ControlLabel>Billing Address Line 2</ControlLabel>
<FormControl
name ="billingAddressLine2"
type="text"
value={fields.billingAddressLine2}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="billingAddressCountry" bsSize="large">
<ControlLabel>BillingAddressCountry</ControlLabel>
<CountryDropdown
name="billingAddressCountry"
value={fields.billingAddressCountry}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="mailingAddressRegion" bsSize="large">
<ControlLabel>Billing Address Region</ControlLabel>
<RegionDropdown
name="mailingAddressRegion"
country={fields.billingAddressCountry}
value={fields.billingAddressRegion}
onChange={handleFieldChange} />
</FormGroup>
<FormGroup controlId="billingCity" bsSize="large">
<ControlLabel>City</ControlLabel>
<FormControl
name = "billingCity"
type="text"
value={fields.billingAddressCity}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="billingZipCode" bsSize="large">
<ControlLabel>Zip Code</ControlLabel>
<FormControl
name = "billingZipCode"
type="text"
value={fields.billingAddressZip}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="gender" bsSize="sm">
<ControlLabel>Gender</ControlLabel>
<br></br>
<ControlLabel>Male</ControlLabel>
<FormControl
name = "gender"
type="radio"
onChange={handleFieldChange}
value={fields.gender}
checked={fields.gender === 'male'}
/>
<ControlLabel>Female</ControlLabel>
<FormControl
name = "gender"
type="radio"
onChange={handleFieldChange}
value={fields.gender}
checked={fields.gender === 'female'}
/>
<ControlLabel>Other</ControlLabel>
<FormControl
name = "gender"
type="radio"
onChange={handleFieldChange}
value={fields.gender}
checked={fields.gender === 'other'}
/>
</FormGroup>
<FormGroup controlId="onList" bsSize="sm">
<br></br>
<ControlLabel>Join Email List</ControlLabel>
<br></br>
<ControlLabel>Yes</ControlLabel>
<FormControl
name = "onList"
type="checkbox"
onChange={handleFieldChange}
value={fields.onList}
checked={fields.onList === 'true'}
/>
</FormGroup>
<FormGroup controlId="dateOfBirth">
<ControlLabel>Date of Birth</ControlLabel>
<DatePicker
name="dateOfBirth"
value={fields.dateofBirth}
selected={fields.dateOfBirth}
onChange={handleFieldChange}
locale="en"
/>
</FormGroup>
<FormGroup controlId="content">
<ControlLabel>Notes Area</ControlLabel>
<FormControl
name = "content"
value={fields.content}
componentClass="textarea"
onChange={handleFieldChange}
/>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isLoading}
disabled={!validateForm()}
>
Signup
</LoaderButton>
</form>
);
}
return (
<div className="Signup">
{newUser === null ? renderForm() : renderConfirmationForm()}
</div>
);
}
This is a clever approach to handling change events and persisting values to state. You do, however, put a lot of faith in this component library to fire onChange events consistently with their HTML counterparts.
I noticed in the docs that the onChange is a little different than you might expect:
<CountryDropdown
value={country}
onChange={(val) => this.selectCountry(val)} />
<RegionDropdown
country={country}
value={region}
onChange={(val) => this.selectRegion(val)} />
Both of these expect an arrow function handler to receive the val property, so you might consider rewriting your implementation:
<CountryDropdown
name = "mailingAddressCountry"
country={fields.mailingAddressCountry}
value={fields.mailingAddressCountry}
onChange={(val) => updateField({ mailingAddress: val})} />
And modify your hook to so that you aren't working from the bare event. It'll require a little more syntax, and there's probably a cleaner way to approach, but it will give you the control you need to handle edge cases. Something like so:
import { useState } from "react";
export function useFormFields(initialState) {
const [fields, setValues] = useState(initialState);
return [
fields,
function(value) {
setValues({
...fields,
...value
});
}
];
}

Routing between SignUp and SignIn Components

Here's my Content wrapper which will either display the SignUp component or the SignIn component.
const Content = (props) => {
return (
<div className="wrapper">
<SignIn/>
<SignUp/>
</div>
)
};
export default Content;
Here's my SignUp component
class SignUp extends React.Component {
state = {
email: '',
username: '',
password: '',
second_password: '',
showModal: false,
modalMessage: '',
modalHeader: ''
};
handleSubmit = async (event) => {
event.preventDefault();
const emailValidated = await this.validateEmail(this.state.email);
const usernameValidated = this.validateUsername(this.state.username);
const passwordValidated = this.validatePassword(this.state.password, this.state.second_password);
if (emailValidated === true){
if(usernameValidated === true){
if(passwordValidated === true){
const registrationComplete = await this.register(this.state.email, this.state.username, this.state.password);
if (registrationComplete === true) {
this.setState(prevState => ({
...prevState,
showModal: true,
modalMessage: "Please check your mail to activate your account",
modalHeader: "Success!"
}));
}else{
this.setState(prevState => ({
...prevState,
showModal: true,
modalMessage: "Something went wrong with the registration. Please try again later.",
modalHeader: "Failure!"
}));
}
}else{
this.setState(prevState => ({
...prevState,
showModal: true,
modalMessage: "Passwords do not match",
modalHeader: "Failure!"
}));
}
}else{
this.setState(prevState => ({
...prevState,
showModal: true,
modalMessage: "Username should be a minimum of 8 characters long",
modalHeader: "Failure!"
}));
}
}else{
this.setState(prevState => ({
...prevState,
showModal: true,
modalMessage: "An account with that email already exists.",
modalHeader: "Failure!"
}));
}
};
validateUsername = (username) => {
return username.trim().length >= 8;
};
validatePassword = (password, second) => {
return password.trim() === second.trim();
};
validateEmail = async (email) => {
const resp = await axios({
method: 'post',
url: 'bouncr/user/exists',
data: {"email": email}
});
return resp.status === 200
};
register = async (email, username, password) => {
const resp = await axios({
method: 'post',
url: 'bouncr/user/register',
data: {'email': email, 'username': username, 'password': password}
});
return resp.status === 201
};
onClose = () => {
this.setState(prevState => ({...prevState, showModal: false, modalMessage: '', modalHeader: ''}));
};
render() {
return (
<div>
<CustomModal
showModal={this.state.showModal}
onClose={this.onClose}
modalMessage={this.state.modalMessage}
modalHeader={this.state.modalHeader}
/>
<div className="register">
<h1>Sign Up</h1>
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId="email">
<Form.Label>Email address</Form.Label>
<Form.Control type="email"
placeholder="Enter email"
value={this.state.email}
onChange={event => this.setState({email: event.target.value})}/>
<Form.Text className="text-muted">
Please make sure you've access to this mail. You'll receive an activation code here.
</Form.Text>
</Form.Group>
<Form.Group controlId="username">
<Form.Label className="form-label">Username</Form.Label>
<Form.Control type="text"
placeholder="Username"
value={this.state.username}
onChange={event => this.setState({username: event.target.value})}/>
<Form.Text className="text-muted">
Please make it atleast 8 characters long.
</Form.Text>
</Form.Group>
<Form.Group controlId="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password"
placeholder="Password"
value={this.state.password}
onChange={event => this.setState({password: event.target.value})}/>
<Form.Text className="text-muted">
Please make sure it's atleast 8 characters long and uses a mix of letters and numbers.
</Form.Text>
</Form.Group>
<Form.Group controlId="confirmPassword">
<Form.Label>Confirm Password</Form.Label>
<Form.Control type="password"
placeholder="Password"
value={this.state.second_password}
onChange={event => this.setState({second_password: event.target.value})}/>
</Form.Group>
<Button variant="primary" type="submit">
Sign Up
</Button>
<hr/>
<p onClick={() => this.props.setIsNew(false)}>
If you don't have an account, Sign Up
</p>
</Form>
</div>
</div>
);
}
}
export default SignUp;
And here's the SignIn component.
const SignIn = () => {
return (
<div className="sign-up">
<h1>Sign In</h1>
<Form>
<Form.Group controlId="email">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" placeholder="Enter email"/>
<Form.Text className="text-muted">
</Form.Text>
</Form.Group>
<Form.Group controlId="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Password"/>
</Form.Group>
<Form.Group controlId="formBasicCheckbox">
<Form.Check type="checkbox" label="Remember me"/>
</Form.Group>
<Button variant="primary" type="submit">
Sign In
</Button>
<hr/>
<p>If you don't have an account, Sign Up</p>
</Form>
</div>
)
};
export default SignIn;
I want the text underneath the button to route to the relevant component. How do I do this with React router?
Manage state in parent component. This is a basic example using hooks. This component will determine which child component is rendered based on it's state.
const Content = props => {
const [isNew, setIsNew] = useState(true);
return (
<div className="wrapper">
{isNew ? <SignUp setIsNew={setIsNew} /> : <SignIn setIsNew={setIsNew} />}
</div>
);
};
export default Content;
Pass setIsNew to children and call with proper boolean values. We pass this function and bind it to an onClick handler.
const SignIn = ({setIsNew}) => {
return (
<div className="sign-up">
<h1>Sign In</h1>
<Form>
<Form.Group controlId="email">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" placeholder="Enter email" />
<Form.Text className="text-muted"></Form.Text>
</Form.Group>
<Form.Group controlId="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Password" />
</Form.Group>
<Form.Group controlId="formBasicCheckbox">
<Form.Check type="checkbox" label="Remember me" />
</Form.Group>
<Button variant="primary" type="submit">
Sign In
</Button>
<hr />
<p onClick={() => setIsNew(true)}>
If you don't have an account, Sign Up
</p>
</Form>
</div>
);
};
export default SignIn;
Same thing as SignIn.
const SignUp = ({setIsNew}) => {
return (
<div className="sign-up">
<h1>Sign In</h1>
<Form>
<Form.Group controlId="email">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" placeholder="Enter email" />
<Form.Text className="text-muted"></Form.Text>
</Form.Group>
<Form.Group controlId="username">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" placeholder="Username" />
<Form.Text className="text-muted"></Form.Text>
</Form.Group>
<Form.Group controlId="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Password" />
</Form.Group>
<Form.Group controlId="confirmPassword">
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Confirm Password" />
</Form.Group>
<Button variant="primary" type="submit">
Sign In
</Button>
<hr />
<p onClick={() => setIsNew(false)}>
If you don't have an account, Sign Up
</p>
</Form>
</div>
);
};
export default SignUp;

Categories

Resources