How to add email validation to below code? - reactjs

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.

Related

Fields tied to the state doesn't clear on successful form submission

I have a contact form, when the form submission is successful it should clear the form field name, email and message which is tied up to the state. The form submission is successful but form fields name, email and message doesn't clear.
For test purpose what I'm doing is passing default values to the state but this values doesn't get filled in form during initial load.
export default function Contact() {
const [name, setName] = useState('John Doe')
const [email, setEmail] = useState('me#example.com')
const [message, setMessage] = useState('Hello, this is test message.')
const onSubmit = (e) => {
e.preventDefault()
const form = {"name": name, "email": email, "message": message}
return fetch('/api/contact', {
method: 'POST',
body: JSON.stringify(form),
headers: {'Content-Type': 'application/json'}
}).then(response => {
if(response.status === 200){
setName('')
setEmail('')
setMessage('')
} else {
}
}).catch(err => err)
}
return (
<section>
<form method='post'>
<div>
<label>Name</label>
<input type="text" name="name" onChange={(e) => {setName(e.target.value)}}/>
</div>
<div>
<label>Email Address</label>
<input type="email" name="email" onChange={(e) => {setEmail(e.target.value)}}/>
</div>
<div>
<label>Message</label>
<textarea minLength={5} maxLength={2000} rows="6" name="message" onChange={(e) => {setMessage(e.target.value)}}></textarea>
</div>
<div>
<button type='submit' onClick={(e) => {onSubmit(e)}}>Send Message</button>
</div>
</form>
</section>
);
}
As User456 said, you need to add value={variable} for every <input />.
Example:
import { useState } from "react";
export default function Contact() {
const [name, setName] = useState("John Doe");
const [email, setEmail] = useState("me#example.com");
const [message, setMessage] = useState("Hello, this is test message.");
const onSubmit = (e: any) => {
e.preventDefault();
setName("");
setEmail("");
setMessage("");
};
return (
<section>
<form method="post">
<div>
<label>Name</label>
<input
type="text"
name="name"
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
</div>
<div>
<label>Email Address</label>
<input
type="email"
name="email"
value={email}
onChange={e => {
setEmail(e.target.value);
}}
/>
</div>
<div>
<label>Message</label>
<textarea
minLength={5}
maxLength={2000}
name="message"
value={message}
onChange={e => {
setMessage(e.target.value);
}}></textarea>
</div>
<div>
<button
type="submit"
onClick={e => {
onSubmit(e);
}}>
Send Message
</button>
</div>
</form>
</section>
);
}

React js firebase empty field validation

I have created a form in react and store the details in firebase but my problem is even if the feilds are empty the form is submitted, i want validation that feild should not be empty if the user wants to submit.
const Account2 = () => {
const [kookid, setKookID] = useState("");
const [kookname, setKookName] = useState("");
const userCollectionRef = collection(db, "mastermenu")
const handleSubmit = () => {
addDoc(userCollectionRef,{
kookid: kookid,
kookname: kookname,
}).then(() => {
if(!alert("form Submitted Successfully!!!"));
navigate("/account");
})
return (
<><div className='outer-container'>
<h1 className='text-3xl font-bold py-2'>MASTER MENU</h1>
</div>
<div className='outer-container'>
<form className='contactform'>
<label>Kook ID</label>
<input
placeholder=""
onChange={(e) => setKookID(e.target.value) } />
<label>Kook Name</label>
<input
required
placeholder=""
onChange={(e) => setKookName(e.target.value)} />
</form>
<button onClick={handleSubmit}>Submit</button>
</div></>
)
}

How to activate button in condition

const Login = () => {
const [ID, setID] = useState();
const [PW, setPW] = useState();
function handleIdInput(event) {
setID(event.target.value);
console.log(ID);
}
function handlePWInput(event) {
setPW(event.target.value);
console.log(PW);
}
<form>
<div>
<input type="text" id="ID" className="boxes" onChange={handleIdInput} />
</div>
<div>
<input
type="password"
id="password"
className="boxes"
onChange={handlePWInput}
/>
</div>
<button className="boxes" type="button" onClick={goList}>
LogIn
</button>
</form>;
};
I want to activate the button if id includes # and password has at least 7 characters. I'm trying to find a way not to use class and this method. Thank you!
Please make use of disabled property.
<button className='boxes' type='button' onClick={goList} disabled={()=> checkDisabled(ID, PW)}>
LogIn
</button>
The checkDisabled function must return true or false based on your requirements.
const checkDisabled = (id, password) => {
// condition here
if(id.includes('#') && password.length >= 7)
{
return false;
}
return true;
}
Then finally the component code must look like this. Please note the changes I have made related to how the state variables are connected with the input component.
import { useState } from "react";
const Login = () => {
const [ID, setID] = useState("");
const [PW, setPW] = useState("");
function handleIdInput(event) {
setID(event.target.value);
console.log(ID);
}
function handlePWInput(event) {
setPW(event.target.value);
console.log(PW);
}
const checkDisabled = (id, password) => {
// condition here
if (id.includes("#") && password.length >= 7) {
return false;
}
return true;
};
return (
<form>
<div>
<input
type="text"
id="ID"
className="boxes"
value={ID}
onChange={(e) => handleIdInput(e)}
/>
</div>
<div>
<input
type="password"
id="password"
className="boxes"
value={PW}
onChange={(e) => handlePWInput(e)}
/>
</div>
<button
className="boxes"
type="button"
onClick={goList}
disabled={() => checkDisabled(ID, PW)}
>
LogIn
</button>
</form>
);
};
export default Login;
Reference for useState hook.

How to validate email and password using react hooks?

I am getting state values while clicking submit button but I am unable to do the validation for my login form and how to display the error messages below the input field when I enter my input wrong or empty. please give me a solution to this.Thanks in advance.
const Login = () => {
const [state, setState] = useState({
email: "",
password: ""
});
const handleChange = (e) => {
const {id, value} = e.target
setState(prevState => ({
...prevState,
[id]: value
}))
}
const handleSubmitClick = (e) => {
e.preventDefault();
console.log("Authenticated",state);
}
return(
<>
<div className="container">
<div className="title">
<form onSubmit={handleSubmitClick}>
<div className="form-group">
<input
type="email"
className="email"
placeholder="Email"
value={state.email}
onChange={handleChange}/>
</div>
<div className="form-group">
<input
type="password"
className="password"
placeholder="Password"
value={state.password}
onChange={handleChange}/>
</div>
<button type="submit" className="button">Enter</button>
</form>
</div>
</div>
</>
)
}
export default Login;
If you want to perform client-side validation, you can create hook like this:
const useEmailValidation = (email) => {
const isEmailValid = /#/.test(email); // use any validator you want
return isEmailValid;
};
And then you can use this hook in your form component:
...
const isEmailValid = useEmailValidation(state.email);
const isPasswordValid = usePasswordValidation(state.password);
const isFormValid = isEmailValid && isPasswordValid;
return (
...
<input
className={classNames({ 'invalid': !isEmailValid })}
type="email"
value={state.email}
onChange={handleChange}
/>
{!isEmailValid && 'Some error message'}
<button type="submit" disabled={!isFormValid} className="button">Enter</button>
...
);
...
Your validator hook can return validation message instead of boolean, like:
const useEmailValidation = (email) => {
if (!email || email.length === 0) {
return 'Email cannot be empty';
}
const isEmailValid = /#/.test(email); // use any validator you want
if (!isEmailValid) {
return 'Invalid email provided';
}
return null;
};
Also it is a good practice to show validation message only after field was focused before and after user tried to submit the form.
Formik is a great plugin that will help you perform form validation. The examples are also quite clear.
Or you could do something like this:
const Login = () => {
const [error, setError] = useState(null);
const [state, setState] = useState({
email: '',
password: '',
});
const validateEmail = (email) => {
const re =
/^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
};
const handleChange = (e) => {
const { id, value } = e.target;
setState((prevState) => ({
...prevState,
[id]: value,
}));
};
const handleSubmitClick = (e) => {
e.preventDefault();
if (!validateEmail(state.email)) {
setError('Invalid Email');
}
if (state.password.length < 8) {
setError('Password must be at least 8 chars long');
}
if (!error) {
// No errors.
}
};
return (
<>
<div className='container'>
<div className='title'>
{error && <div style={{ color: 'red' }}>{error}</div>}
<form onSubmit={handleSubmitClick}>
<div className='form-group'>
<input
type='email'
className='email'
placeholder='Email'
value={state.email}
onChange={handleChange}
/>
</div>
<div className='form-group'>
<input
type='password'
className='password'
placeholder='Password'
value={state.password}
onChange={handleChange}
/>
</div>
<button type='submit' className='button'>
Enter
</button>
</form>
</div>
</div>
</>
);
};
export default Login;
For an empty validation you can check it preventing the submit if the field is empty, like
const handleSubmitClick = (e) => {
e.preventDefault();
if(email.trim() === '' || password.trim() === ''){
//Add a h1 or section with the error message
}else{
console.log("Authenticated",state);
}
}
As long as the email field type is equal to email, which is your case, the browser should give an alert if the string is not an email. ("user#example.com")

How to write validations for email and password using react hooks

I am working on React in that project I am trying to write validations for Email and password by
using react hooks But I don't know how to start it write it so please help to achieve this.
What I want exactly is I hard coded Email and Password in my code. Now Just I want to write validations for Email and Password. What I want exactly is If I enter Incorrect Email and Correct password then in Validations it have to show only please enter valid email address.
If I enter correct Email then it has to show please enter correct password. If both are wrong means then it has to show validations please enter correct Email and Password.
This is my code
import React, { useState } from 'react';
import './Login.css';
const Login = () => {
const [loginData, setLoginData] = useState(null)
const loginCredentials = () => {
if (loginData.email === 'john#gmail.com' && loginData.password === 'christina') {
} else {
}
}
const handleChange = ({ target }) => {
const { name, value } = target
const newData = Object.assign({}, loginData, { [name]: value })
setLoginData(newData)
}
const handleSubmit = (e) => {
e.preventDefault()
loginCredentials()
}
return (
<div className='container'>
<div className='row justify-content-center'>
<div className='col-4'>
<div className='mainform mt-3'>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="email">Email</label>
<input type="email" name='email' className="form-control" id="email" onChange={handleChange}></input>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input type="password" name='password' className="form-control" id="password" onChange={handleChange}></input>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</div>
)
}
export default Login
Try saving the errors in an array and check the length of array at the end.
const [errors,setErrors]=useState([]);
.
.
.
if(username !='john#gmail.com')
{
setErrors([...errors,{error:'Invalid username'}])
}
if(password!='something')
{
setErrors([...errors,{error:'Invalid password'}])
}
Now inside of the component
{errors?errors.map(elem=>elem.error):null}
You can create a state for the error message and change its value based on what combination of email and password is incorrect. If
const [errorMessage, setErrorMessage] = useState('')
const loginCredentials = () => {
if (loginData.email !== 'john#gmail.com' && loginData.password !== 'christina') {
setErrorMessage('email and pw are both incorrect')
} else if (loginData.email !== 'john#gmail.com' {
setErrorMessage('email is incorrect')
} else if {.....etc
}
then put {errorMessage} in your jsx where you want it to show up
You can use nested if else
const [error, setError] = useState("");
const loginCredentials = () => {
if (loginData.email === "john#gmail.com") {
if (loginData.password === "christina") {
setError("");
return true;
}
else
{
setError("Incorrect Password");
return false;
}
} else {
setError("Incorrect Email and password");
return false;
}
};
To show the error you can put a div somewhere in the form which will only show when there is error.
{error && <div>{error}</div>}
First of all, your input values are not controlled elements. learn about 'controlled component'.
There are lots of ways you can achieve this.
I think you can add a custom hook to handle onChange and reset handler.
custom hook:
import { useState } from 'react';
const useInputState = (initialValues) => {
const [state, setstate] = useState(initialValues);
const onChangeHandler = (e) => setstate({
...state,
[e.target.name]: e.target.value,
});
const reset = (field) => {
if (field) {
setstate({
...state,
[field]: initialValues[field],
});
} else {
setstate({
...initialValues,
});
}
};
return [state, onChangeHandler, reset];
};
export default useInputState;
Then consume that hook in your component.
import React, { useState } from 'react';
import UseInputState from '../hooks/useInputState';
const App = () => {
const [value, onChangeHandler, reset] = UseInputState('');
console.log({ value });
const [emailAlert, setEmailAlert] = useState(null);
const [passwordAlert, setPasswordAlert] = useState(null);
const loginCredentials = () => {
setEmailAlert(null);
setPasswordAlert(null);
const { email, password } = value;
if (email !== 'john#gmail.com') {
setEmailAlert('Please Enter valid Email Address');
}
if (password !== 'christina') {
setPasswordAlert(' please enter correct password');
}
reset('');
if (password === 'christina' && email === 'john#gmail.com') {
setEmailAlert(null);
setPasswordAlert(null);
}
};
const handleSubmit = (e) => {
e.preventDefault();
loginCredentials();
};
return (
<div className='container'>
<div className='row justify-content-center'>
<div className='col-4'>
<div className='mainform mt-3'>
<form onSubmit={handleSubmit}>
<div className='form-group'>
<label htmlFor='email'>Email</label>
<input
type='email'
name='email'
className='form-control'
id='email'
value={value.email || ''}
onChange={onChangeHandler}
></input>
</div>
<div className='form-group'>
<label htmlFor='password'>Password</label>
<input
type='password'
name='password'
className='form-control'
id='password'
value={value.password || ''}
onChange={onChangeHandler}
></input>
</div>
<button type='submit' className='btn btn-primary'>
Submit
</button>
</form>
{emailAlert && <div>{emailAlert}</div>}
{passwordAlert && <div>{passwordAlert}</div>}
</div>
</div>
</div>
</div>
);
};
export default App;

Resources