Validation in Form with React js and Firebase - reactjs

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

Related

Login Validation Wrong React Node js

i am creating a simple login form using frontend react backend node js.while attempt to login login failure. if we type wrong email and password alert msg displays login success. i don't know why.my backend i tested through postman it is work well.check through react had a problem.what i tried so far i attached below.
import axios from "axios";
import { useState } from "react";
import { useNavigate } from 'react-router-dom';
function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
async function login(event) {
event.preventDefault();
try {
await axios.post("http://localhost:9992/student/login", {
email: email,
password: password,
});
alert("Login Successfully");
// navigate('/home');
} catch (err) {
alert("ogin Failed");
}
}
return (
<div>
<div class="container">
<div class="row">
<h2>Login</h2>
<hr/>
</div>
<div class="row">
<div class="col-sm-6">
<form>
<div class="form-group">
<label>email</label>
<input type="email" class="form-control" id="email" placeholder="Enter Name"
value={email}
onChange={(event) => {
setEmail(event.target.value);
}}
/>
</div>
<div class="form-group">
<label>password</label>
<input type="password" class="form-control" id="password" placeholder="Enter Fee"
value={password}
onChange={(event) => {
setPassword(event.target.value);
}}
/>
</div>
<button type="submit" class="btn btn-primary" onClick={login} >Login</button>
</form>
</div>
</div>
</div>
</div>
);
I am using the data value based on your comment.
Modify your login function as following:
async function login(event) {
event.preventDefault();
try {
const res = await axios.post("http://localhost:9992/student/login", {
email: email,
password: password,
});
const data = res.data;
if (data.status === true) {
alert("Login Successfully");
} else {
alert("Login failed")
}
} catch (err) {
alert("Error, please try again");
}
}

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.

Can't verify email and password from Firebase

I'm creating a signup form and trying to get the email and password to work. When I used input and set the state with the appropriate values, it works just fine, but once I wrap the Input around my custom component its unable to get data from the component into the state and gives me an error that a user cannot be found (even if their info is in the Firebase Auth)
I need help.
Auth.js
import style from "./auth.module.css";
import { useEffect, useRef, useState } from "react";
import { useAuthState } from 'react-firebase-hooks/auth';
import { auth, signInWithEmailAndPassword, signInWithGoogle } from "../../firebase";
import { CSSTransition } from "react-transition-group";
export default function Auth() {
const [activeMenu, setActiveMenu] = useState("main");
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [user, loading, error] = useAuthState(auth);
let domNode = useClickOutside(() => {
setActiveMenu(false);
});
return (
<div className={style.container}>
<Login />
<Signup />
</div>
);
function AuthType(props) {
return (
<a
href={props.link}
className={style.menuItem}
onClick={() => props.goToMenu && setActiveMenu(props.goToMenu)}
>
{props.children}
</a>
);
}
/* I believe you've switched up the login and sign-up? */
function Login() {
return (
<CSSTransition in={activeMenu === "main"} unmountOnExit timeout={500}>
<div ref={domNode}>
<div className={style.login}>
<h1 className={style.title}>Clip It</h1>
{/* Email and Password */}
<Emailform
label="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Passform
label="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<div className={style.button}>
<input
type="submit"
value="Login"
onClick={() => signInWithEmailAndPassword(email, password)} />
<input
type="submit"
value="Login with Google"
onClick={signInWithGoogle} />
</div>
<div className={style.text}>
<p className={style.plink}>Forgot Password</p>
<div>
Need an account?
<AuthType goToMenu="Signup">click here</AuthType>
</div>
</div>
</div>
</div>
</CSSTransition>
);
}
function Signup() {
return (
<CSSTransition in={activeMenu === "Signup"} unmountOnExit timeout={500}>
<div ref={domNode}>
<div className={style.signUp}>
<div className={style.title}> Clip It</div>
<Form label="First Name" type="text" />
<Form label="Last Name" type="Text" />
<Form label="Email" type="email" />
<Form label="Date of Birth" type="date" />
<Form label="Password" type="password" />
<Form label="Confirm Password" type="password" />
<div className={style.button}>
<input type="submit" value="Sign Up" />
</div>
<div className={style.text}>
have an
<AuthType goToMenu="main"> account</AuthType>
</div>
</div>
</div>
</CSSTransition>
);
}
}
let useClickOutside = (handler) => {
let domNode = useRef();
useEffect(() => {
let clickListener = (event) => {
if (domNode.current && !domNode.current.contains(event.target)) {
handler();
}
};
document.addEventListener("mousedown", clickListener);
return () => {
document.removeEventListener("mousedown", clickListener);
};
});
return domNode;
};
function Form(props) {
return (
<div className={style.formBox}>
<label className={style.label}>{props.label}:</label>
<form className={style.input}>
<input
type={props.input}
name={props.input}
required="true" />
</form>
</div>
);
}
function Emailform(props) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
return (
<div className={style.formBox}>
<label className={style.label}>{props.label}:</label>
<form className={style.input}>
<input
type="email"
name={props.input}
required="true"
value={email}
onChange={(e) => setEmail(e.target.value)} />
</form>
</div>
);
}
function Passform(props) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
return (
<div className={style.formBox}>
<label className={style.label}>{props.label}:</label>
<form className={style.input}>
<input
type="text"
name={props.input}
required="true"
value={password}
onChange={(e) => setPassword(e.target.value)} />
</form>
</div>
);
}
Firebase.js
import firebase from 'firebase/app';
//import * as firebase from "firebase/app";
import "firebase/auth"
import "firebase/firestore"
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyCq8BAlTWJXG7rFU95QkUTU8U0kXruPA9o",
authDomain: "clip-it-70ff5.firebaseapp.com",
databaseURL: "https://clip-it-70ff5-default-rtdb.firebaseio.com",
projectId: "clip-it-70ff5",
storageBucket: "clip-it-70ff5.appspot.com",
messagingSenderId: "637963668511",
appId: "1:637963668511:web:9cbd1deae03b819153d92a",
measurementId: "G-8S1G78ZH49"
};
const app = !firebase.apps.length ? firebase.initializeApp(firebaseConfig) : firebase.app();
const auth = app.auth();
const db = app.firestore();
/* Using Google Authentication */
const googleProvider = new firebase.auth.GoogleAuthProvider();
//
const signInWithGoogle = async () => {
try {
const res = await auth.signInWithPopup(googleProvider);
const user = res.user;
const query = await db
.collection("users")
.where("uid", "==", user.uid)
.get();
if (query.docs.length === 0) {
await db.collection("users").add({
uid: user.uid,
name: user.displayName,
authProvider: "google",
email: user.email,
});
alert("You're logged in");
}
} catch (err) {
console.error(err);
alert(err.message);
}
};
/* Using Email and Password */
// Sign/Logging In
const signInWithEmailAndPassword = async (email, password) => {
try {
await auth.signInWithEmailAndPassword(email.trim(), password);
alert("You've logged in successfuly");
} catch (err) {
console.error(err);
alert("The email or password is incorrect, please try again");
}
};
//SigningUp
const registerWithEmailAndPassword = async (name, email, password) => {
try {
const res = await auth.createUserWithEmailAndPassword(email.trim(), password);
const user = res.user;
await db.collection("users").add({
uid: user.uid,
name,
authProvider: "local",
email,
});
} catch (err) {
console.error(err);
alert(err.message);
}
};
//Sending Password reset link
const sendPasswordResetEmail = async (email) => {
try {
await auth.sendPasswordResetEmail(email);
alert("Password reset link sent!");
} catch (err) {
console.error(err);
alert(err.message);
}
};
const logout = () => {
auth.signOut();
}; // Log out
export {
signInWithGoogle,
signInWithEmailAndPassword,
registerWithEmailAndPassword,
sendPasswordResetEmail,
logout,
auth,
db,
};
Your code has a list of issues.
You have email/password states in both EmailForm/PassForm, as well as the parent (Auth) component.
You're setting values and trying to handle onChange on the EmailForm/PassForm components, but you never actually call these props, and you never actually set some of the props you're trying to access (ex: name={props.input}).
The inputs inside those two components are setting the email/password states to themselves, yet your Auth component is feeding Firebase its own states for email/password, which you never actually set.
You should also never use an input of type="text" for password fields.
If you insist on keeping the structure you currently have, move the EmailForm and PassForm functions inside to your Auth component, remove the props you're setting onto them, remove their states, and just use the Auth component's state.
// Inside the Auth component
const EmailForm = () => {
return (
<div className={style.formBox}>
<label className={style.label}>{props.label}:</label>
<form className={style.input}>
<input
type="email"
name="email"
required="true"
value={email}
onChange={(e) => setEmail(e.target.value)} />
</form>
</div>
);
}
const PassForm = () => {
return (
<div className={style.formBox}>
<label className={style.label}>{props.label}:</label>
<form className={style.input}>
<input
type="password"
name="password"
required="true"
value={password}
onChange={(e) => setPassword(e.target.value)} />
</form>
</div>
);
}
Then call them with a simple
<EmailForm />
<PassForm />

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;

How to find display error message from API in reactjs

I'm new to React.JS, creating an app for contacts. From API, the fields of contact got validated, if same name or phone number exists then it will show error message in API. My query is how to show the error message in UI while entering the same name or phone number. Do I need to fetch from Contact API? If yes, I could fetch the API of contacts in DIdmount but don't know how to show the error? Can any one help me in this?
Create a state variable for error with the initial value set to "" or null. Make the api call, the server (assuming you are also building the server) should check to see if the name and phone number already exist. If they already exist the server should return an error. In your react app catch the error after your API call and assign it to your state variable for error. Here is an example for the client using hooks.
export default function RegistrationForm(props) {
const [error, setError] = useState(null)
const errorDiv = error
? <div className="error">
<i class="material-icons error-icon">error_outline</i>
{error}
</div>
: '';
const handleSubmit = e => {
e.preventDefault();
setError(null);
const { full_name, user_name, password } = e.target;
AuthApiService.postUser({
full_name: full_name.value,
user_name: user_name.value,
password: password.value
})
.then(user => {
full_name.value = '';
user_name.value = '';
password.value = '';
props.onRegistrationSuccess();
})
.catch(res => {
setError(res.error);
})
};
return(
<form className='RegistrationForm'
onSubmit={handleSubmit}
>
<div className='full_name'>
<label htmlFor='RegistrationForm__full_name'>
Full name
</label>
<Input
name='full_name'
type='text'
required
id='RegistrationForm__full_name'>
</Input>
</div>
<div className='user_name'>
<label htmlFor='RegistrationForm__user_name'>
User name
</label>
<Input
name='user_name'
type='text'
required
id='RegistrationForm__user_name'>
</Input>
</div>
<div className='password'>
<label htmlFor='RegistrationForm__password'>
Password
</label>
<Input
name='password'
type='password'
required
id='RegistrationForm__password'
>
</Input>
</div>
<div className='confirm-password'>
<label htmlFor="LoginForm__confirm-password">
Retype Password
</label>
<Input
name='confirm-password'
type="password"
required
id="LoginForm__confirm-password">
</Input>
</div>
{errorDiv}
<Button type='submit' variant='contained' color='default'>
Register
</Button>
</form>
)
}
Yes if you want exact error message from api response than you can get this by
.then(responseJson=> { console.log(responseJson.response.data.message) })
Have an API to check if the name is available or not, and hit the API when the user changes something in the input.
import React, { useState } from "react";
import ReactDOM from "react-dom";
let delayTimer;
function App() {
const [name, setName] = useState("");
const [nameAvailable, setNameAvailable] = useState(null);
async function checkNameAvailable() {
try {
const response = await APIUtility.isNameAvailable(name);
const { data = null } = response;
if (data) {
setNameAvailable(data); // data may be true or false
}
} catch (error) {
setNameAvailable(null);
}
}
function handleNameChange(e) {
setName(e.target.value);
if (name.length > 0) {
if (delayTimer) clearTimeout(delayTimer);
delayTimer = setTimeout(function() {
checkNameAvailable();
}, 1000); // Will do the ajax stuff after 1000 ms, or 1 s
}
}
return (
<form>
<label htmlFor="invite_code">Enter your name:</label>
<input
value={name}
onChange={handleNameChange}
type="text"
name="inviteCode"
id="invite_code"
autoComplete="off"
/>
{nameAvailable && <span>Name already taken</span>}
</form>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Resources