values on handleSubmit() shows undefined in console log - reactjs

The same code worked well in the Previous machine.
Now for some reason, the values in console (in handleSubmit()) shows undefined for email, fullName, and password and then it reaches catch block saying something went wrong! Help.
I have a Signup form:
export default function MerchantCreateAccountForm() {
Constants such as email, password and name are defined in it:
// set error messages to display to the user
const [nameError, setNameError] = useState(null);
const [emailError, setEmailError] = useState(null);
const [passwordError, setPasswordError] = useState(null);
// set initial state value(s)
const [fullName, setFullName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [errors, setErrors] = useState({});
const authContext = useContext(AuthContext);
Mainly, NEED HELP HERE FOR undefined VALUES FOR email, fullName AND password in handleSubmit()
Later it reaches to catch block(something went wrong) but that can be another issue.
Here's the function:
const handleSubmit = (e) => {
try {
e.preventDefault();
console.log("email is: " +email); //showing undefined in console. HELP
console.log("name is: "+fullName); //showing undefined in console. HELP
console.log("password is: "+password); //showing undefined in console. HELP
const merchantSignupData =
{
data:
{
name: fullName,
email: email,
password: password,
client_id: 'testclient',
client_secret: 'testpass'
},
type: 'POST',
url: 'merchant-signup',
success: authContext.merchantSignupSuccess,
error: authContext.networkError
};
merchantSignupObject.fullName, merchantSignupObject.password);
authContext.merchantSignup(merchantSignupData);
}
catch{
console.log("something went wrong!");
//need to add error handling here
}
}
I have used validations here although, that works fine, just in case if this might be hampering of setting up the data:
// for every change in our state this will be fired
// we add validation here and disable the save button if required
useEffect(() => {
// we want to skip validation on first render
if (firstRender.current) {
firstRender.current = false
return
}
// here we can disable/enable the save button by wrapping the setState function
// in a call to the validation function which returns true/false
//setDisabled(formValidation())
formValidation();
}, [fullName, password]) // any state variable(s) included in here will trigger the effect to run
// here we run any validation, returning true/false
const formValidation = () => {
let newErrors = {}
var error = false;
if (fullName === "") {
newErrors.fullName = 'Name cant be blank!'
}
if (email === "") {
newErrors.email = 'Email cant be blank!'
}
if (!(/.+#.+\.[A-Za-z]+$/.test(email))) {
newErrors.email = 'Enter a valid email id';
}
if (!(/(?=.{7,255}$)(?=.*[A-Z])(?=.*[a-z])(?=.*\d)/.test(password))) {
newErrors.password = 'Invalid Password Format';
}
setNameError(errors.name)
setEmailError(errors.email)
setPasswordError(errors.password)
if (errors != null) {
//alert("reached")
setErrors(newErrors);
// $("#signup-submit").addremoveAttr("disabled")
}
else {
alert("reached here")
setNameError(errors.fullName)
setEmailError(errors.email)
setPasswordError(errors.password)
// $("#signup-submit").removeAttr("disabled")
}
}
const showError = () => {
alert('error!');
}
And here's my main form:
return (
<form onSubmit={handleSubmit()}>
<div className="row">
<div className="col-md-4 col-sm-6 col-xs-12">
<div className="signup">
<h3>{lang.merchant_signup_create_account}</h3>
<p>{lang.merchant_signup_account_already}{lang.merchant_signup_sign_in}</p>
<div className="form-group has-error">
<input type="text" required="required" name="fullName"
value={fullName}
placeholder={lang.merchant_signup_name_placeholder}
onChange={e => setFullName(e.target.value)} />
<label htmlFor="input" className="control-label">{lang.merchant_signup_name}</label>
<i className="bar"></i>
<div className="error">
<div className="error-msg" role="alert">
{errors.fullName && <p>{errors.fullName}</p>}
</div>
</div>
</div>
<div className="form-group">
<input type="text" required="required"
placeholder={lang.merchant_signup_email_placeholder} onChange={e => setEmail(e.target.value)} />
<label htmlFor="E-mail" className="control-label">{lang.merchant_signup_email}</label><i className="bar"></i>
<div className="error">
<div className="error-msg" role="alert">
{errors.email && <p>{errors.email}</p>}
</div>
</div>
</div>
<div className="form-group">
<input type="password" required="required" placeholder={lang.merchant_signup_password_placeholder} onChange={e => setPassword(e.target.value)} />
<label htmlFor="Password" className="control-label">{lang.merchant_signup_password}</label><i className="bar"></i>
<div className="error">
<div className="error-msg" role="alert">
{errors.password && <p>{errors.password}</p>}
</div>
</div>
<ul className="p-suggest">
<li> {lang.merchant_signup_password_validation1}</li>
<li>{lang.merchant_signup_password_validation2}</li>
</ul>
<ul className="p-suggest">
<li>{lang.merchant_signup_password_validation3}</li>
<li>{lang.merchant_signup_password_validation4}</li>
</ul>
</div>
<p>{lang.merchant_signup_create_terms_warning}<a target="_blank" href="#">{lang.merchant_terms_condition}</a>.</p>
</div>
<ul className="list-inline">
{/* onClick={() => handleSubmit()} */},
<li><button type="submit" id="signup-submit" className="btn btn-danger create-account next-step">{lang.merchant_signup_create_account_btn}</button></li>
</ul>
</div>
<div className="col-md-8 col-sm-6 col-xs-12">
<img className="img-responsive" src={storeImg} />
</div>
</div>
</form>
)
}

As you can read see here,
Make sure you aren’t calling the function when you pass it to the component:
So, change your form onSubmit method invocation to
<form onSubmit={handleSubmit}>
or
<form onSubmit={() => handleSubmit()}>

Back to basics, Silly solution:
The attribute value is missing in each input and it was henceforth taking value to be undefined like following:
<input value={password} type="password" required="required" placeholder={lang.merchant_signup_password_placeholder} onChange={e => setPassword(e.target.value)} />

Related

How to add email validation to below code?

The below code is using cards to show account creation, deposit and other module.
I need to refractor the code to add email, name, and password field validation, but I am not able to do it.
context.js
const Route = ReactRouterDOM.Route;
const Link = ReactRouterDOM.Link;
const HashRouter = ReactRouterDOM.HashRouter;
const UserContext = React.createContext(null);
function Card(props){
function classes(){
const bg = props.bgcolor ? ' bg-' + props.bgcolor : ' ';
const txt = props.txtcolor ? ' text-' + props.txtcolor: ' text-white';
return 'card mb-3 ' + bg + txt;
}
return (
<div className={classes()} style={{maxWidth: "18rem"}}>
<div className="card-header">{props.header}</div>
<div className="card-body">
{props.title && (<h5 className="card-title">{props.title}</h5>)}
{props.text && (<p className="card-text">{props.text}</p>)}
{props.body}
{props.status && (<div id='createStatus'>{props.status}</div>)}
</div>
</div>
);
}
function CardForm(props) {
const ctx = React.useContext(UserContext);
return (
<>
<div style={{maxWidth: "18rem"}}>
<div className="name-field" style={{display: props.showName}}>
Name<br/>
<input type="input"
id="txtName"
className="form-control"
placeholder="Enter name"
onChange={e => ctx.name=e.currentTarget.value} /><br/>
</div>
<div className="email-field" style={{display: props.showEmail}}>
Email address<br/>
<input type="input"
id="txtEmail"
className="form-control"
placeholder="Enter email"
onChange={e => ctx.email=e.currentTarget.value}/><br/>
</div>
<div className="password-field" style={{display: props.showPassword}}>
Password<br/>
<input type="password"
id="txtPassword"
className="form-control"
placeholder="Enter password"
onChange={e => ctx.password=e.currentTarget.value}/><br/>
</div>
<div className="amount-field" style={{display: props.showAmount}}>
Amount<br/>
<input type="number"
className="form-control"
placeholder="Enter amount"
onChange={e => ctx.balance=e.currentTarget.value}/><br/>
</div>
</div>
</>
)
}
creatAccount.js
function CreateAccount(props){
const [show, setShow] = React.useState(true);
const [status, setStatus] = React.useState('');
const ctx = React.useContext(UserContext);
function addUser() {
ctx.balance = '0';
fetch(`/account/find/${ctx.email}`)
.then(response => response.json())
.then(data => {
console.log(data);
if (data.length===0) ctx.user = true;
})
.then(() => {
if (ctx.user===true) {
const url = `/account/create/${ctx.name}/${ctx.email}/${ctx.password}/${ctx.balance}`;
(async () => {
var res = await fetch(url);
var data = await res.json();
console.log(data);
})();
ctx.user='';
setShow(false);
} else {
ctx.user='';
setStatus('User already exists with that email');
setTimeout(() => setStatus(''),3000);
}})
}
return (
<Card
bgcolor="primary"
header="Create Account"
text=""
status={status}
body={
<>
{show ?
<>
<CardForm setShow={setShow} showAmount="none"/>
{<button type="submit" className="btn btn-light" onClick={addUser}>Create Account</button>}
</>
:
<Success setShow={setShow}/>}
</>
}
/>
);
}
function Success(props) {
return (
<>
<h5>Success!</h5><br/>
<button type="submit"
className="btn btn-light"
onClick={() => props.setShow(true)}>Add another account</button>
</>
)
}
I have tried multiple solutions from online content, but they do not solve the problem.
Lets simplify this
Using NPM package email-validator
Install via NPM
npm install email-validator
import * as EmailValidator from 'email-validator';
Bind your local state to your input field e.g
const [email, setEmail] = useState("");
const [valid, setIsValid] = useState(false);
<input
type="text"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
Create a function to check for email validation like below
const validateEmail = (email) => {
setIsValid(EmailValidator.validate(email));
};
Now there comes two cases. One is to show the validation on change the input field or check on submitting the whole form. To give the validation message while inputting email, you have to use the useEffect hook just like below
useEffect(() => {
if (email) {
validateEmail(email);
}
}, [email, validateEmail]);
You can use the valid state for validation message while user is entering the email something like below
<span>{valid ? 'Email format valid' : 'Invalid email format'} <span>
Second Case
just call the function we created above for email validation and check the valid state.

Validation in Form with React js and Firebase

import React, { useState, useEffect } from "react";
import {db} from './firebase'
//I want to add some validation which perform task as follows
//1. Check user enter username less then 40 words
//2. Check user enter email (it need to check basic email information like # symbol)
//3. Check Message should not be exceed then 400 words ,
// All filed must be filled .
const Contact = () => {
const [senderName,setSenderName] = useState("");
const [senderEmail,setSenderEmail] = useState("");
const [senderMessage,setSenderMessage] = useState("");
const handleSubmitForm = (e) => {
e.preventDefault();
db.collection('Contact_Form').add({
User_name:senderName,
User_email:senderEmail,
User_message:senderMessage
})
.then(()=>{
alert("Message submitted")
})
.catch((error) => {
alert(error.message);
});
setSenderName("");
setSenderEmail("");
setSenderMessage("");
};
return(
<>
<div className="contact_us_body">
<div className="contact_us_container">
<div className="contact_us_content">
<div className="contact_us_right_side">
<div className="text_heading">Send us a message</div>
<form className="form" onSubmit={handleSubmitForm} >
<div className="contact_us_input_box">
<input type="text" placeholder="Enter your name" value={senderName}
onChange = {(e) => setSenderName(e.target.value)} />
</div>
<div className="contact_us_input_box">
<input type="text" placeholder="Enter your email"value={senderEmail}
onChange={(e) => setSenderEmail(e.target.value)} />
</div>
<div className="contact_us_input_box message-box">
<textarea name="messageText" id="" cols="30" rows="10"
placeholder="Type your Message"value={senderMessage}
onChange={(e) => setSenderMessage(e.target.value)} >
</textarea>
</div>
<div className="contact_us_button">
<input type="submit" value="Send Now" />
</div>
</form>
</div>
</div>
</div>
</div>
</>
)
}
export default Contact;
For Authenticating the Range of characters in username
function stringlength(inputtxt, maxlength)
{
var field = inputtxt.value;
var mxlen = maxlength;
if(field.length> mxlen)
{
alert("Please input the userid between " +mnlen+ " and " +mxlen+ " characters");
return false;
}
}
If you are using Firebase than you can use firebase Authentication for the login and it will take care of the email formatting-
first of all, define 2 additional useState to show the errors,
const [emailError, setEmailError] = useState('');
const handleLogin = () => {
db
.auth()
.signInWithEmail(email)
.catch((err) =>{
switch (err.code){
case "auth/invalid-email":
// console.log(err)
setEmailError(err.message);
break;
}
})
}
For Limiting the Characters in the tag, use the following attribute
<textarea maxlength="400">

My react form is not submitting correctly

i have a problem with my react's form.
If I click twice on the submit button then at this moment, the form submits correctly and sends my various information to the database.
Where is the problem ?
import React, { useState } from 'react';
import axios from 'axios';
const Register = () => {
const [username, setUsername] = useState();
const [password, setPassword] = useState();
const onSubmit = (e) => {
e.preventDefault();
setUsername(document.querySelector(".usernameInput").value);
setPassword(document.querySelector(".passwordInput").value);
const user = {
username: username,
password: password
}
axios.post('http://localhost:5000/users/add', user)
.then(res => console.log(res.data));
console.log("lancement du formulaire");
}
return (
<div>
<h1>TEST Form</h1>
<form onSubmit={onSubmit}>
<div className="form-group">
<label>Username</label>
<input required type="text" className="usernameInput" />
</div>
<div className="form-group">
<label>Password</label>
<input required type="password" />
</div>
<div className="form-group">
<input type="submit" value="Create User" className="btn btn-primary" className="passwordInput" /> </div>
</form>
</div>
)
}
export default Register;
Thanks .
useState is asynchronous just like setState in class components. You can't update the state on one line and assume it's already changed on the next one. You'll likely use the unchanged state.
When you create the user object, the state is not yet updated.
You need to click twice on the submit button because:
on the first click you set the username and password states' value to the input value but as the state is not updated, you send the user objects with empty properties
on the second click (when the state is updated) you can send the user object, as the user object contains the state values
The following should work (though I would recommend not to use it):
const onSubmit = (e) => {
e.preventDefault();
const user = {
username: document.querySelector('.usernameInput').value,
password: document.querySelector('.passwordInput').value,
};
axios
.post('http://localhost:5000/users/add', user)
.then((res) => console.log(res.data));
console.log('lancement du formulaire');
};
But why do you use states username and password if you never use them? If you've already added the states to store the input values, you can update them on changes and submit them on form submit:
const Register = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const onSubmit = (e) => {
e.preventDefault();
const user = {
username,
password,
};
axios
.post('http://localhost:5000/users/add', user)
.then((res) => console.log(res.data));
console.log('lancement du formulaire');
};
return (
<div>
<h1>TEST Form</h1>
<form onSubmit={onSubmit}>
<div className="form-group">
<label>Username</label>
<input
required
type="text"
className="usernameInput"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div className="form-group">
<label>Password</label>
<input
required
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="form-group">
<input
type="submit"
value="Create User"
className="btn btn-primary"
className="passwordInput"
/>{' '}
</div>
</form>
</div>
);
};

React function Component Validation

I am a beginner in react. I was working on the react function component with forms using hooks. Can anyone please tell how can I apply validation on email text when it is invalid or empty, and disable the continue button if the form is not valid.
import React, { useState } from "react";
const ForgotPassowrd = () => {
const [emailId, setemailId] = useState("");
const forgotPasswordClick = (event) => {};
return (
<div>
<div className="NewPassword-form form_wrapper">
<div className="form-body">
<form action="#">
<div>
<div className="form-group">
<label htmlFor="password">Email-Id</label>
<div className="input-group">
<input type="text" className="form-control" value={emailId} onChange={(event)=>
setemailId(event.target.value)}/>
</div>
</div>
<button type="button" onClick={forgotPasswordClick} className="btn btn-lg
btn-block">Continue</button>
</div>
</form>
</div>
</div>
</div>
);
};
export default ForgotPassowrd;
**Try it.This may be helpfull for you! If you can any queries comment below.**
const LoginV2 = ({}) => {
// state
const [loginForm, setLoginForm] = useState({
email: undefined,
password: undefined,
emailValid: false,
passwordValid: false,
});
const [error, setError] = useState({ email: undefined, password: undefined });
// state update
const handleLoginForm = (e) => {
checkValidity(e.target.name, e.target.value);
setLoginForm({ ...loginForm, [e.target.name]: e.target.value });
};
// validation function
const checkValidity = (inputName, inputValue) => {
switch (inputName) {
case "email":
let pattern = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
loginForm.emailValid = pattern.test(inputValue);
break;
case "password":
loginForm.passwordValid = inputValue.length >= 6;
break;
default:
break;
}
};
// form submit
const onSubmitLoginForm = () => {
console.log(loginForm);
if (!loginForm.emailValid) {
setError(prevError => {
return {
...prevError,
email: "Invalid Email Address"
}
});
}
if (!loginForm.passwordValid) {
setError(prevError => {
return {
...prevError,
password: "Password must be at least six characters long"
}
});
}
return (
<div class="row">
<div class="form">
<div class="col span-1-of-2">
<div class="username">
<p class="login-para text-align-center">LOG IN VIA EMAIL</p>
<form method="post" action="#" class="login-form">
{error.email && (
<div class="alert alert-danger">
<p>
{" "}
<strong> {alertText} </strong> {error.email}
</p>
</div>
)}
{error.password && (
<div class="alert alert-danger">
<p>
{" "}
<strong> {alertText} </strong> {error.password}
</p>
</div>
)}
<div class="info-box">
{icon && <i class="fas fa-user-alt login-icon"></i>}
<input
type="text"
name="email"
placeholder="Your Email"
onChangeText={(e) => handleLoginForm(e)}
inputValue={loginForm.email}
/>
</div>
<div class="info-box">
{icon && <i class="fas fa-user-alt login-icon"></i>}
<input
type="password"
name="password"
placeholder="Your Password"
onChangeText={(e) => handleLoginForm(e)}
inputValue={loginForm.password}
/>
</div>
<div class="buttons">
<input type="checkbox" />
<label class="remember" for="#">
Remember me
</label>
<div class="form-btn-disabled" onClick={onSubmitLoginForm}
>
LOGIN NOW
</div>
</div>
</form>
</div>
</div>
</div>
</div>
);
};
export default LoginV2;
Try below. I have added inline comments for better understanding. Comment your queries if you have any.
// Regex to check valid email
const validEmail = /^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$/g
import React, { useState } from "react";
const ForgotPassowrd = () => {
const [emailId, setemailId] = useState("");
//State to disable/enable continue button
const [disableBtn, setDisableBtn] = useState(false);
const forgotPasswordClick = (event) => {};
const handleSubmit = e => {
e.preventDefault();
// Do whatever you want to do after you click submit button
}
const handleChange = e => {
setemailId(event.target.value);
setDisableBtn(validEmail.test(e.target.value));
}
return (
<div>
<div className="NewPassword-form form_wrapper">
<div className="form-body">
{/* Remove action and use onSubmit handler*/}
<form onSubmit={handleSubmit}>
<div>
<div className="form-group">
<label htmlFor="password">Email-Id</label>
<div className="input-group">
{/* Introduced name attribute to help you with handleSubmit handler*/}
<input name="email" type="text" className="form-control" value={emailId} onChange={(event)=>
setemailId(event.target.value)}/>
</div>
</div>
<button onClick={forgotPasswordClick} className="btn btn-lg
btn-block" disabled={disableBtn}>Continue</button>
</div>
</form>
</div>
</div>
</div>
);
};
export default ForgotPassowrd;

What mean "form submitting canceled"?

Get warning in console when trying to submit login form (form submission canceled because the form is not connected). If deleting if (isAuthed) return <Redirect to="/additem" />; my form became are connected. In other issues people say 'replace type of button from submit to button'. It doesn't work. How can I connect form?
export function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [isAuthed, setIsAuthed] = useState(false);
console.log(isAuthed);
function onChangeUsername(e) {
setUsername(e.target.value)
}
function onChangePassword(e) {
setPassword(e.target.value)
}
function getToken() {
const token = Date.now().toString();
if (username && password) {
localStorage.setItem('userToken', JSON.stringify(token));
setIsAuthed(true)
}
}
//if (isAuthed) return <Redirect to="/additem" />;
return (
<div className="col-md-12">
<div className="card card-container">
<form onSubmit={getToken} noValidate>
<span className="fas fa-sign-in-alt"/>
<div className="form-group">
<label htmlFor="username">Username</label>
<input type="text" className="form-control"
name="username"
value={username}
onChange={onChangeUsername}
placeholder="Login"
required
/>
<div className="invalid-feedback">
Wrong username
</div>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
name="password"
value={password}
onChange={onChangePassword}
placeholder="Password"
required
/>
<div className="invalid-feedback">
Wrong password
</div>
</div>
<div className="form-group">
<button className="btn btn-primary" type="submit">
Submit form
</button>
</div>
</form>
</div>
</div>
)
}
First of your form is submitting except you're doing one thing which is not getting you your expected results. You will need to prevent the default behavior with form submission. Preventing the default behavior will prevent the page from reloading which is the normal behavior with form submission.
function getToken(event) {
event.preventDefault();
const token = Date.now().toString();
if (username && password) {
localStorage.setItem('userToken', JSON.stringify(token));
setIsAuthed(true)
//you can then redirect here. Example
//pass in a props then props.history.push("/additem");
}
}

Resources