Using useMediaQuery how can we make the screen responsive? - reactjs

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;

Related

How to validate if first array doesn't have value from second array by radio buttons with YUP

I select first radio button to render first array of radio buttons with colors, select one of the colors, then I select second radio to render second array of radio buttons with colors. If my selected color from first array doesn't include of second array, how to show error?
CodeSandbox: https://codesandbox.io/s/focused-microservice-l4q3re?file=/src/App.tsx
import React, { useState } from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "#hookform/resolvers/yup";
import * as yup from "yup";
export default function App() {
const schema = yup.object().shape({
choose: yup.string().typeError("select first or second").required(),
color: yup
.string()
.typeError("selected color doesn't include of this array")
.required("select color")
});
const {
register,
formState: { errors },
handleSubmit
} = useForm({
resolver: yupResolver(schema)
});
const onSubmit = (data: any) => {
console.log(data);
};
const onError = (error: any) => {
console.log(error);
};
let colors = [
["black", "white", "pink"],
["black", "red", "blue"]
];
const [select, setSelect] = useState<number>();
return (
<form onSubmit={handleSubmit(onSubmit, onError)}>
<label>
<input
type="radio"
onClick={() => setSelect(0)}
value={"first"}
{...register("choose")}
/>
first
</label>
<label>
<input
type="radio"
onClick={() => setSelect(1)}
value={"second"}
{...register("choose")}
/>
second
</label>
<p> {errors && errors.choose?.message}</p>
<div>
{select != null &&
colors[select].map((color: any, i: number) => (
<label key={i}>
<input
type="radio"
value={color}
{...register("color")}
/>
{color}
</label>
))}
{select != null && <p> {errors && errors.color?.message}</p>}
</div>
<button type="submit">Add</button>
</form>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
The final code for App.tsx
Paste this in App.tsx in your given sandbox to see the result.
import React, { useState } from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "#hookform/resolvers/yup";
import * as yup from "yup";
export default function App() {
const schema = yup.object().shape({
choose: yup.string().typeError("select first or second").required(),
color: yup
.string()
.typeError("selected color doesn't include of this array")
.required("select color")
});
const {
register,
formState: { errors },
handleSubmit
} = useForm({
resolver: yupResolver(schema)
});
const onSubmit = (data: any) => {
console.log(data);
};
const onError = (error: any) => {
console.log(error);
};
let colors = [
["black", "white", "pink"],
["black", "red", "blue"]
];
const [select, setSelect] = useState<number>();
const [validationState, setValidationState] = useState<boolean>();
const onClickChildRadio = (value: string) => {
const secondArray:string[] = colors[1];
const isExistInSecondArray = secondArray.includes(value);
setValidationState(isExistInSecondArray);
};
return (
<form onSubmit={handleSubmit(onSubmit, onError)}>
<label>
<input
type="radio"
onClick={() => setSelect(0)}
value={"first"}
{...register("choose")}
/>
first
</label>
<label>
<input
type="radio"
onClick={() => setSelect(1)}
value={"second"}
{...register("choose")}
/>
second
</label>
<p> {errors && errors.choose?.message}</p>
<div>
{select != null &&
colors[select].map((color: any, i: number) => (
<label key={i}>
<input
onClick={(e) => onClickChildRadio(e.target.value)}
type="radio"
value={color}
{...register("color")}
/>
{color}
</label>
))}
{select != null && <p> {errors && errors.color?.message}</p>}
</div>
<button type="submit">Add</button>
<p>
Validate :
{validationState
? "Value exist in second array"
: "Value doesn't exist in second array"}
</p>
</form>
);
}

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

Form values coming as blank on submit

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

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;

i am trying to create a custom hook for form validation

I am a React beginner and have been trying to make a custom error handler hook for my contact form.
I have done everything I knew, but I cannot get it to fire submit a message or error message. I am not sure what type should be for callback and validation in UseForm.tsx, and I don't know if the ValidateLogin interface is correct.
This is my code:
UseForm.tsx:
import React, {useState, useEffect} from "react";
const UseForm = (callback:any, validate:any) => {
const [contact, setContact] = useState({
name: "",
email: "",
title: "",
content: ""
});
const [errors, setErrors] = useState({
name: "",
email: "",
title: "",
content: ""
});
const [isSubmitting, setIsSubmitting] = useState(false);
function handleChange(e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) {
const {name, value} = e.target
setContact({...contact, [name]: value})
}
const handleSubmit = (e:React.ChangeEvent<HTMLFormElement>) => {
e.preventDefault();
setErrors(validate(contact));
setIsSubmitting(true);
};
useEffect(() => {
if (Object.keys(errors).length === 0 && isSubmitting) {
callback();
}
}, [errors]);
return {
handleChange,
handleSubmit,
contact,
errors
};
};
export default UseForm
ValidateLogin.tsx:
interface Contact {
email: string;
name: string
title:string
content:string
}
type Error = Partial<Contact>
const ValidateLogin = (contact: Contact) => {
let errors: Error= {};
if (!contact.email) {
} else if (!/\S+#\S+\.\S+/.test(contact.email)) {
errors.email = "Email address is invalid";
}
if (!contact.name) {
errors.name = "Name is required";
}
if (!contact.title) {
errors.title = "Title is required";
}
if (!contact.content) {
errors.content = "Content is required";
}
return errors;
}
export default ValidateLogin
Contact.tsx:
import React from "react";
import {useStep} from "react-hooks-helper";
import useForm from "../components/UseForm"
import validate from "../components/ValidateLogin";
const Contact: React.FC = () => {
const {handleChange, handleSubmit, contact, errors} = useForm(
submit,
validate
);
function submit() {
console.log("Submitted Succesfully");
}
const {index, navigation: {previous, next},} = useStep({steps: 4});
return (
<div className="contact">
<div className="contact-inner">
<form onSubmit={handleSubmit} noValidate>
{index === 0 && <label>
<input onChange={handleChange} value={contact.name} type="text" name="name"
placeholder="Please enter your name"/>
{!errors.name && <p className="error">{errors.name}</p>}
</label>}
{index === 1 && <label htmlFor="email">
<input onChange={handleChange} value={contact.email} type="email" name="email"
placeholder="Please enter your email"/>
{errors.email && <p className="error">{errors.email}</p>}
</label>}
{index === 2 && <label>
<input onChange={handleChange} value={contact.title} type="text" name="title"
placeholder="Please enter the title"/>
{errors.title && <p className="error">{errors.title}</p>}
</label>}
{index === 3 && <label>
<textarea onChange={handleChange} value={contact.content} className="content" name="content"
placeholder="Please enter your message"/>
{errors.content && <p className="error">{errors.content}</p>}
</label>}
</form>
<div className="buttons">
{index === 0 ? <button onClick={previous} disabled>Previous</button> :
<button onClick={previous}>Previous</button>}
{index === 3 ? <button type="submit">Submit</button> : <button onClick={next}>Next</button>}
</div>
</div>
</div>
)
}
export default Contact

Resources