Form values coming as blank on submit - reactjs

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

Related

Using useMediaQuery how can we make the screen responsive?

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;

my react js app is not working - Display react DOM error -How to fix it

The error, Module not found: Error: Can’t resolve ‘react-dom/client’, is seen because you still have the previous outdated versions of “react” and “react-dom” installed in the dependencies of your project file
I would like to share the steps that helped me to fix the error; Module not found: Error: Can’t resolve ‘react-dom/client’.
this is my js files
Register component:
import React, { useState, useEffect } from "react";
import axios from "axios";
function Register() {
const [name, setName] = useState();
const [email, setEmail] = useState();
const [password, setPassword] = useState();
const saveData = (e) => {
e.preventDefault();
const user = { name, email, password };
axios.post(`http://localhost:8000/user/register`, user).then((res) => {
alert("user registered");
console.log(res.data);
});
};
return (
<div>
<form onSubmit={saveData}>
<input
type="text"
placeholder="Enter name"
value={name}
style={{ margin: 5 }}
onChange={(e) => setName(e.target.value)}
/>
<br />
<input
type="text"
placeholder="email"
value={email}
style={{ margin: 5 }}
onChange={(e) => setEmail(e.target.value)}
/>
<br />
<input
type="text"
placeholder="Passsowrd"
value={password}
style={{ margin: 5 }}
onChange={(e) => setPassword(e.target.value)}
/>
<br />
<button type="submit"> Submit</button>
</form>
</div>
);
}
export default Register;
Login component:
import React, { useState } from "react";
import axios from "axios";
const Login = () => {
const [user, setUser] = useState({ email: "", password: "" });
const onChangeHandler = (e) => {
setUser({ ...user, [e.target.name]: e.target.value });
};
const loginHandler = async (e) => {
e.preventDefault();
if (user.name === "" || user.password === "") {
alert("Fill all the fields");
} else {
try {
const res = await axios.post("http://localhost:8000/user/login", {
...user,
});
window.sessionStorage.setItem("user", res.data.user._id);
window.sessionStorage.setItem("name", res.data.user.name);
localStorage.setItem("firstLogin", true);
console.log(res);
alert("logged in succesfully");
window.location.reload();
} catch (error) {
alert("invalid email or Password");
}
}
};
console.log(user);
return (
<div>
Login
<br />
<br />
<label>Email</label>
<br />
<input
type="email"
name="email"
defaultValue={user.email}
onChange={onChangeHandler}
/>
<br />
<label>Password</label>
<br />
<input
type="password"
name="password"
defaultValue={user.password}
onChange={onChangeHandler}
/>
<br />
<button onClick={loginHandler}>Submit</button>
<br />
</div>
);
};
export default Login;
how can i fix this issue

Error : not able to write anything into React input feild

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}
/>

Two times click is necessary to Login in ReactJS

I am trying to make a Login page and I am successful in some way. So here is my Login component:
import React, { useState, useEffect } from "react";
import Axios from "axios";
import useForm from "../components/LoginForm/useForm";
import validate from "components/LoginForm/validate";
import redtruck from "../assets/img/red-truck.png";
import auth from "../Authentication/auth";
import { withRouter } from "react-router";
const Login = ({ submitForm, history }) => {
const [isSubmitted, setIsSubmitted] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const [login, setLogin] = useState(false);
async function submitForm() {
setIsSubmitted(true);
try {
await fetchLogin(values.email, values.password);
if(login){
auth.login(() => {
history.push("/admin");
});
}
} catch (e) {
auth.login(() => {
history.push("/");
})
}
}
const { handleChange, values, handleSubmit, errors } = useForm(
submitForm,
validate
);
useEffect(() => {
if (localStorage.getItem("user-info")) {
submitForm();
}
}, []);
const fetchLogin = async (email, password) => {
try {
setLoading(true);
const res = await Axios({
method: "POST",
url: `url`,
headers: {
},
data: {
user_email: email,
user_password: password,
},
});
if (res.status === 200) {
setLogin(true);
localStorage.setItem("user-info", JSON.stringify(res.data));
}
setLoading(false);
} catch (err) {
setError(err.message);
setLoading(false);
}
};
return (
<>
<div>
<div className="form-container">
<div className="form-content-left">
<img className="form-img" src={redtruck} alt="spaceship" />
</div>
<div className="form-content-right">
<h1>SIGN IN</h1>
<form className="form" onSubmit={handleSubmit}>
<div className="form-inputs">
<label htmlFor="email" className="form-label">
Email address
</label>
<input
id="signin-email"
type="email"
name="email"
placeholder="Enter email"
className="form-input"
value={values.email}
onChange={handleChange}
/>
{errors.email && <p>{errors.email}</p>}
</div>
<div className="form-inputs">
<label htmlFor="password" className="form-label">
Password
</label>
<input
id="signin-password"
type="password"
name="password"
placeholder="Password"
className="form-input"
value={values.password}
onChange={handleChange}
/>
{errors.password && <p>{errors.password}</p>}
{login ? "" : <p>The password or the email is wrong</p>}
</div>
<button
variant="primary"
type="submit"
className="form-input-btn"
>
LOGIN
</button>
</form>
</div>
</div>
</div>
</>
);
};
export default withRouter(Login);
So the login state is set to true when email and password are right for the user. Later I want to use it when redirecting page to "/admin". But my problem is I have to click twice to login in the first place. Besides I am not sure, if the catch part is right:
catch (e) {
auth.login(() => {
history.push("/");
})
}
So I would be really glad, if you can give me some hint about it.
Thanks...
it is not that you have to press twice, you can check component state, sometimes React batches setState and then update value. You can look at this setState doesn't update the state immediately

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