This is the first web app that im building using react and im completely lost in validating the login and this is the code i follow and im not able to type anything into the field.
The error occurs during validating since previous i used this and works well before i tried to validate.
import React , {Fragment, useState,useEffect} from 'react'
import { useDispatch , useSelector} from 'react-redux'
import {useAlert} from 'react-alert'
import MetaData from '../layouts/MetaData'
import Loader from '../layouts/Loader'
import { Link, useLocation } from 'react-router-dom'
import {userLogin, clearErrors} from '../../actions/users'
import { useNavigate ,useParams} from 'react-router-dom'
const Login = () => {
const dispatch= useDispatch();
const alert=useAlert();
//const [email,setEmail]=useState('');
//const [password,setPassword]=useState('');
const initialValues = { email: "", password: "" };
const [formValues, setFormValues] = useState(initialValues);
const [formErrors, setFormErrors] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
let navigate=useNavigate();
let location =useLocation();
const {isAuthenticated,error,loading}=useSelector(state =>state.auth);
const redirect=location.search ? location.search.split('=')[1] : '/'
useEffect(()=>{
if(isAuthenticated){
navigate(redirect)
}
if(error){
alert.error(error);
dispatch(clearErrors());
}
}, [dispatch, alert, isAuthenticated, error, navigate])
const handleChange = (e) => {
const { name, value } = e.target;
setFormValues({ ...formValues, [name]: value });
};
const loginHandler = (ev) => {
ev.preventDefault()
setFormErrors(validate(formValues));
setIsSubmit(true);
dispatch(userLogin(formValues.email,formValues.password));
}
useEffect(() => {
console.log(formErrors);
if (Object.keys(formErrors).length === 0 && isSubmit) {
console.log(formValues);
}
}, [formErrors]);
const validate = (values) => {
const errors = {};
const regex = /^[^\s#]+#[^\s#]+\.[^\s#]{2,}$/i;
if (!values.username) {
errors.username = "Username is required!";
}
if (!values.email) {
errors.email = "Email is required!";
} else if (!regex.test(values.email)) {
errors.email = "This is not a valid email format!";
}
if (!values.password) {
errors.password = "Password is required";
} else if (values.password.length < 4) {
errors.password = "Password must be more than 4 characters";
} else if (values.password.length > 10) {
errors.password = "Password cannot exceed more than 10 characters";
}
return errors;
};
return (
<Fragment>
{loading ?<Loader></Loader> :(
<Fragment>
<MetaData title={'Login'} />
<div className="row wrapper">
<div className="col-10 col-lg-5">
<form className="shadow-lg" onSubmit={loginHandler}>
<h1 className="mb-3">Login</h1>
<div className="form-group">
<label htmlFor="email_field">Email</label>
<input
type="email"
id="email_field"
className="form-control"
value={formValues.email}
onChange={handleChange}
/>
</div>
<div className="form-group">
<label htmlFor="password_field">Password</label>
<input
type="password"
id="password_field"
className="form-control"
value={formValues.password}
onChange={handleChange}
/>
</div>
<Link to="/password/forgot" className="float-right mb-4">Forgot Password?</Link>
<button
id="login_button"
type="submit"
className="btn btn-block py-3"
>
LOGIN
</button>
<Link to="/register" className="float-right mt-3">New User?</Link>
</form>
</div>
</div>
</Fragment>
)}
</Fragment>
)}
export default Login
Thanks a lot in advance!!
You are missing name prop (attribute) in your JSX.
Due to this your function is failing to update the state with correct values.
const handleChange = (e) => {
const { name, value } = e.target;
// name will be undefined, because you haven't set it.
setFormValues({ ...formValues, [name]: value });
};
Simply Add name and it will work.
<input
type="email"
id="email_field"
name="email"
className="form-control"
value={formValues.email}
onChange={handleChange}
/>
<input
type="password"
id="password_field"
className="form-control"
name="password"
value={formValues.password}
onChange={handleChange}
/>
Related
Using useMediaQuery in react responsive, how can we make the Login component responsive for following resolutions ? Could someone please advise here ?
1920 * 1080
1536 * 864
and 1366 * 768
import React, { useState, useEffect, useCallback } from 'react';
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import { useMediaQuery } from 'react-responsive';
const appURL = process.env.REACT_APP_URL;
const Login = () => {
const { register, handleSubmit, formState: { errors }, reset} = useForm();
const [loginData, setLoginData] = useState("");
const [helperText, setHelperText] = useState('');
const navigate = useNavigate();
const isDesktopOrLaptop = useMediaQuery({ maxWidth: 1920 })
const onSubmit = (data) => {
const fetchData = async () => {
try {
const userEmail = "dev#test.com"; // for time being just hard code data
const userPassword = "some_paswword"; // for time being just hard code data
if(data.email === userEmail && data.password === userPassword ){
localStorage.setItem('loginEmail', userEmail);
setLoginData(userEmail);
navigate('/admin');
window.location.reload(true)
} else {
setHelperText("Invalid login details");
}
} catch (e) {
console.log(e);
setHelperText(e.response.data.fail);
}
}
fetchData();
};
console.log(errors);
return (
<div id="App">
{ isDesktopOrLaptop &&
<section className="row">
<div className='loginSection'>
<h3>Login</h3>
<form className='loginForm' onSubmit={handleSubmit(onSubmit)}>
<input
id="email"
type="email"
placeholder='email'
{...register("email", {
required: true,
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
message: "Please enter a valid email !"
}
})}
/>
<span className="emailValidationText">
{errors.email && errors.email.type === "required" && <span>Email is required !</span>}
{errors.email && <span>{errors.email.message}</span>}
</span>
<input
id="password"
type="password"
placeholder='password'
{...register("password", {
required: true,
minLength: {
value: 5,
message: "Minimum length of 5 letters"
},
pattern: {
value: /^(?=.*?\d)(?=.*?[a-zA-Z])[a-zA-Z\d][a-zA-Z\d\#!#~$]+$/,
message: "Password begin with letter, includes number & special character"
}
})}
/>
<span className="passwordValidationText">
{errors.password && errors.password.type === "required" && <span>Password is required !</span>}
{errors.password && <span>{errors.password.message}</span>}
</span>
<label>
<span className="loginValidationText">{helperText}</span>
</label>
<section className="col-low">
<input type="submit" />
</section>
</form>
</div>
</section>
}
</div>
)
}
export default Login;
import { useState } from "react";
function App() {
const initialValues = { username:"", password: "" };
const [formValues, setFormValues] = useState(initialValues);
const [formErrors, setFormErrors] = useState({});
const [isSubmit, setIsSubmit] = useState(
JSON.parse(localStorage.getItem("data")) ? true : false
);
const handleChange = (e) => {
const { name, value } = e.target;
setFormValues({ ...formValues, [name]: value });
};
const handleSubmit = (e) => {
e.preventDefault();
setFormErrors(validate(formValues));
setIsSubmit(true);
};
const validate = (values) => {
const errors = {};
if (!values.username) {
errors.username = "Username is required!";
}
if (!values.password) {
errors.password = "Password is required";
} else if (values.password.length < 4) {
errors.password = "Password must be more than 4 characters";
} else if (values.password.length > 8) {
errors.password = "Password cannot exceed more than 10 characters";
}
return errors;
};
const logout = () => {
setIsSubmit(false);
localStorage.clear();
};
return (
<div className="container">
{Object.keys(formErrors).length === 0 && isSubmit ? (
<>
{localStorage.setItem("data", JSON.stringify(formValues))}
<div>
hello {JSON.parse(localStorage.getItem("data")).username} ,Signed
in successfully
</div>
<button onClick={logout}>LOG OUT</button>
</>
) : (
<form onSubmit={handleSubmit}>
<div>
<div>
<label>Username</label>
<input
type="text"
name="username"
placeholder="Username"
value={formValues.username}
onChange={handleChange}
/>
</div>
<p>{formErrors.username}</p>
<div>
<label>Password</label>
<input
type="password"
name="password"
placeholder="Password"
value={formValues.password}
onChange={handleChange}
/>
</div>
<p>{formErrors.password}</p>
<button>Submit</button>
</div>
</form>
)}
</div>
);
}
export default App;
once data stored in storage
when it get reloaded keys are present but value missing
when form is getting reloaded the data which is stored in the from of object in localStorage the values are getting missed while key are present.when form is getting reloaded the data which is stored in the from of object in local Storage the values are getting missed while key are present.
You need to set the handleSubmit func instead of returning the data to the local storage, as you can see in the code below.
const handleSubmit = (e) => {
e.preventDefault();
setFormErrors(validate(formValues));
setIsSubmit(true);
localStorage.setItem("data", JSON.stringify(formValues));
};
Remove this line {localStorage.setItem("data", JSON.stringify(formValues))} in return method.
Not able to pick the values of email and token from the below form. It is displaying as blank during on click on submit. Can anyone please advise where I am doing wrong ?
https://codesandbox.io/s/dazzling-kirch-1gqq4?file=/src/App.js
import React, { useRef, useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import Axios from "axios";
const CreateLink = () => {
const [email, setEmail] = useState("");
const [token, setToken] = useState("");
const {
handleSubmit,
register,
formState: { errors }
} = useForm();
const onSubmit = (e) => {
e.preventDefault();
alert(`Sending Email ${email}`);
const fetchData = async () => {
try {
const res = await Axios.post(
"http://localhost:8000/service/createlink",
email,
token
);
if (res.data.success) {
console.log("Link token created:" + res.data.success);
}
} catch (e) {
console.log(e);
}
};
fetchData();
};
return (
<div className="App">
<h1>Create Link</h1>
<form onSubmit={handleSubmit(onSubmit)} className="linkForm inputForm">
<div className="inputField">
<input
name="email"
placeholder="email"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
{...register("email", {
required: "Email is required",
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
message: "Invalid email address"
}
})}
/>
<span className="loginErrorTextFormat">
{errors.email && <p>{errors.email.message}</p>}
</span>
</div>
<div className="inputField">
<input
placeholder="token"
name="token"
type="text"
value={token}
onChange={(e) => setToken(e.target.value)}
{...register("token", {
required: "Token is required"
})}
/>
<span className="loginErrorTextFormat">
{errors.token && <p>Input is not valid</p>}
</span>
</div>
<input type="submit" />
</form>
</div>
);
};
export default CreateLink;
Because register return an object has property onChange. So it override your onChange, you just need move onChange after register
{...register("token", {
required: "Token is required"
})}
onChange={(e) => setToken(e.target.value)}
Here I'm trying to build a signup form using the react-hook form. I'm trying to build a restaurant website for my own purpose. But I have tried many times. But I'm getting many errors. First of all when I sign up a new user then firebase is not creating a new user. The form is not validating completely. But I can't find out the problem. Where is the problem? Can anyone help, please?
Here is my signUp.js file
import React, { useEffect, useState } from 'react';
import { useAuth } from './useAuth'
import { useForm } from 'react-hook-form';
import logo from '../../Images/logo2.png';
import './SignUp.css'
const SignUp = () => {
const [returningUser, setReturningUser] = useState(false);
const {register, handleSubmit, watch, errors} = useForm();
const auth = useAuth();
const onSubmit = data => {
if(returningUser){
if(data.email && data.password){
auth.signIn(data.email, data.password)
}
}
else{
if(data.name && data.email && data.password){
auth.signUp(data.email, data.password, data.name)
}
}
}
return (
<div className="sign-up">
<div className="container">
<div className="logo-container ">
<img src={logo} alt=""/>
</div>
{
returningUser ?
<form onSubmit={handleSubmit(onSubmit) } action="" className="py-5">
{
auth && auth.user != null && <p className="text-danger">{auth.user.error}</p>
}
<div className="form-group">
<input name="email" className="form-control" {...register('email', {requried: true})} placeholder="Email"/>
{errors && errors.email && <span className="error">Email is Required</span>}
</div>
<div className="form-group">
<input type="password" name="password" className="form-control" {...register('password', {requried: true})} placeholder="password"/>
{errors&& errors.password && <span className="error">Password is Required</span>}
</div>
<div className="form-group">
<button className="btn btn-danger">Sign In</button>
</div>
<div className="option text-center">
<label onClick={() => setReturningUser(false)}>Create a new Account</label>
</div>
</form>
:
<form action="" onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<input type="text" name="name" className="form-control"
{...register('name', {requried: true})} placeholder="Name"/>
{errors && errors.name && <span className="error">Name is Required</span>}
</div>
<div className="form-group">
<input type="email" name="email" className="form-control" {...register('email', {required: true})} placeholder="Email"/>
{errors && errors.email && <span className="error">Email is required</span>}
</div>
<div className="form-group">
<input type="password" name="password" className="form-control" {...register('password', {requried: true})} placeholder="Password"/>
{errors && errors.password && <span className="error">Password is Required</span>}
</div>
<div className="form-group">
<button className="btn btn-danger" type="submit">Sign Up</button>
</div>
<div className="option text-center">
<label onClick={() => setReturningUser(true)}>Already have an account!</label>
</div>
</form>
}
</div>
</div>
);
};
export default SignUp;
Here is my useAuth.js file
// import { faWindowRestore } from '#fortawesome/free-solid-svg-icons';
import firebase from "firebase/app";
import "firebase/auth";
import firebaseConfig from "../../firebase.config";
import { createContext, useContext, useEffect, useState } from "react";
import { Redirect, Route } from "react-router";
firebase.initializeApp(firebaseConfig);
const AuthContext = createContext();
export const AuthProvider = (props) => {
const auth = Auth();
return (
<AuthContext.Provider value={auth}>{props.children}</AuthContext.Provider>
);
};
export const useAuth = () => {
useContext(AuthContext);
};
export const PrivateRoute = ({ children, ...rest }) => {
let auth = useAuth();
return (
<Route
{...rest}
render={({ location }) =>
auth.user ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location },
}}
/>
)
}
/>
);
};
const Auth = () => {
const [user, setUser] = useState(null);
useEffect(() => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
const currentUser = user;
setUser(currentUser);
// ...
} else {
// User is signed out
// ...
}
});
}, []);
const signIn = (email, password) => {
return firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((res) => {
// Signed in
setUser(res.user);
window.history.back();
// ...
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
});
};
const signUp = (email, password, name) => {
return firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((res) => {
// firebase
// .auth()
// .currentUser.updateProfile({
// displayName: name,
// })
// .then(() => {
setUser(res.user);
window.history.back();
})
// Signed in
// ...
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
// ..
});
};
const signOut = () => {
return firebase
.auth()
.signOut()
.then((res) => {
// Sign-out successful.
setUser(null);
})
.catch((error) => {
// An error happened.
});
};
return {
user,
signIn,
signUp,
signOut,
};
};
export default Auth;
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;