Routing between SignUp and SignIn Components - javascript

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;

Related

I have issue with React forms when I try to post form with file type input

*Hello everyone,
When I try to post form with file type input, my request stuck pending and not add to my database. Can someone help ?
*
this is my upload method.
const addBook = ( name, author, category, about, pdf, image) => {
const book = {
name,
author,
category,
about,
pdf,
image
};
axios.post('http://localhost:3004/book', book)
.then(response => {
books.push(book);
setBooks(books);
});
}
this is my Addbook React function component
const { addBook } = useContext(BookContext);
const [newBook, setNewBook] = useState({
name:"" , author:"", category:"", about:"", pdf:"", image:""
})
const {name, author, category, about, pdf, image} = newBook;
const onInputChange = (e) => {
setNewBook({...newBook, [e.target.name]: e.target.value })
}
const handleSubmit = (e) => {
e.preventDefault();
addBook(name, author, category, about, pdf, image);
}
return (
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Control
type ="Text"
placeholder="Name *"
name="name"
value={name}
onChange={e => onInputChange(e)}
required
/>
</Form.Group>
<Form.Group>
<Form.Control
type ="Text"
placeholder="author *"
name="author"
value={author}
onChange={e => onInputChange(e)}
required
/>
</Form.Group>
<Form.Group>
<Form.Control
as ="textarea"
placeholder="category *"
name="category"
value={category}
onChange={e => onInputChange(e)}
rows={3}
/>
</Form.Group>
<Form.Group>
<Form.Control
type ="Text"
placeholder="about *"
name="about"
value={about}
onChange={e => onInputChange(e)}
/>
</Form.Group>
<Form.Group>
<Form.Control
type ="text"
placeholder="image *"
name="image"
value={image}
onChange={e => onInputChange(e)}
/>
</Form.Group>
<Form.Group>
<Form.Control
type ="file"
placeholder="pdf"
name="pdf"
value={pdf}
onChange={e => onInputChange(e)}
/>
</Form.Group>
<Button variant="success" type="submit" >
Add new Book
</Button>
</Form>
)
}
export default AddBook;
Can you please answer my problem because, I dont have time so much for this project deadline.
thank you for your helping.
Have nice coding everyone... *
Mention Content Type in headers like this
axios.post('http://localhost:3004/book', book,{{headers:{'Content-Type': 'multipart/form-data'}})
.then(response => {
books.push(book);
setBooks(books);
});

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>
);
}
}

Firebase custom fields createUserWithEmailAndPassword after creating user its logging out

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...

Categories

Resources