I am for the first time trying to apply validation in a form using useState (useform.js). I am checking if the number of errors is 0 before a submit. In my case, the error object has zero keys always so any case the form is getting submitted. Please let me know why its happening. Thanks in advance.
contactForm
const ContactForm = () => {
const { handleChange, contact, handleSubmit, errors, handleOnClick } = useform(
submit,
{firstName:"",lastName:"",email:"",phoneNumber:"",message:""}
)
function submit(contact) {
console.log('errors pssed to contact',errors)
if(Object.keys(errors).length === 0){
contactservice.addContact(contact).then(response => {
console.log("Response after post api",response.data);
}).catch(error => {
console.log("Error while post api",error)
})
}
}
return(
<div>
<Header/>
<section id="content">
<div className="container">
<div className="row aln-center">
<div className="col-6 col-12-medium">
<section>
<header>
<h2> Drop your email and phone we will get back !</h2>
<form onSubmit={handleSubmit} noValidate>
<input type='text' placeholder='First Name'value=
{contact.firstName} name='firstName'onChange={handleChange}
autoComplete="off"/>
{errors.firstName && <p>{errors.firstName}</p>}<br/>
<input type='text' placeholder='Last Name' value=
{contact.lastName} name='lastName'onChange={handleChange}
autoComplete="off" /><br/>
{errors.lastName && <p>{errors.lastName}</p>}
<input type='tel' placeholder='Phone Number'value=
{contact.phoneNumber} name='phoneNumber'onChange=
{handleChange} autoComplete="off" /><br/>
{errors.phoneNumber && <p>{errors.phoneNumber}</p>}
<input type='email' placeholder='Email'value=
{contact.email} name='email'onChange={handleChange}
autoComplete="off" />
{errors.email && <p>{errors.email}</p>}
<br/>
<textarea placeholder="Please type what you are
looking from us?" value={contact.message} name
="message" onChange={handleChange}/><br/>
{errors.message && <p>{errors.message}</p>}
<div className="col-6 col-12-xsmall">
<button type='submit'>Submit</button>
<button type='button' onClick=
{handleOnClick}>Cancel</button>
</div>
</form>
</header>
</section>
</div>
</div>
</div>
</section>
</div>
)
}
export default ContactForm;
useform.js
const Useform = (callback, validate) => {
const [contact,setContact] = useState({firstName:"",lastName:"",phoneNumber:"",email:"",message:""});
const [errors,setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
function handleChange(e){
setContact({...contact, [e.target.name] : e.target.value })
}
const handleSubmit = useCallback(e=>{
e.preventDefault();
console.log("contact from handleSubmit",contact)
setErrors(validate(contact));
callback(contact);
});
function validate(contact){
let errors={};
console.log("error object after validation",errors)
if(contact.firstName ==="") {
errors.firstName='Enter a valid firstname'
console.log(" errors.firstName" , errors.firstName)
}
if(contact.lastName ==="") {
errors.lastName='Enter a valid lastname'
console.log(" errors.lastName" , errors.lastName)
}
if(contact.phoneNumber===""){
errors.phoneNumber='Enter a valid phone number up to 10 digit'
console.log("errors.phoneNumber" , errors.phoneNumber)
}
if(contact.email===""){
errors.email="Enter a valid email"
console.log("errors.email" , errors.email)
}
else if(!'/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(contact.email)'){
errors.email="Enter a valid email"
console.log("errors.email" , errors.email)
}
if(contact.message.trim()===""){
errors.message="enter your message"
console.log("errors.message" , errors.message)
}
return (errors);
}
}
const history = useHistory();
function handleOnClick(){
history.push('/dashboard');
}
return
{handleChange,contact,handleSubmit,errors,handleOnClick,validate,isSubmitting};
export default Useform;
Related
I try it but not working
import React from "react";
import "./App.css";
import { useForm } from "react-hook-form";
import classNames from "classnames";
import { useState } from "react";
function App() {
const { register, handleSubmit,formState: { errors } } = useForm();
// console.log(errors);
const onSubmit = data => console.log(JSON.stringify(data));
const postData = async (e)=>{
e.preventDefault();
const res = await fetch("https://test1-5022f-default-rtdb.firebaseio.com/reactformData.json",
{
method:"POST",
header:{
"content-type":"application/json",
},
Here what I pass in body?
body:JSON.stringify(data)
}
)
};
There are many fields in my form but here I show some
return (
<div>
<div className="container">
<div className="form-group my-3 ">
<form name="Registration_form" id="Form" action="" method="POST" onSubmit={handleSubmit(onSubmit)}>
<div className="form-group my-3">
<label htmlFor="name">Name:</label>
<input
type="text"
name="Name"
id="Name"
className={classNames("form-control",{"is-invalid":errors.Name,})}
autoComplete="off"
{...register('Name',
{ required: true,
maxLength: 15,
pattern: /^[A-Za-z]+$/
})
}
/>
<span id="name" className="text-danger fw-bold">{errors.Name?.type === "required" && "This field is required"}</span>
<span id="name" className="text-danger fw-bold">{errors.Name?.type ==="maxLength" && "Length Should be less then 15"}</span>
<span id="name" className="text-danger fw-bold">{errors.Name?.type === "pattern" && "Digits are not allow"}</span>
</div>
</div>
<div className="form-group my-3">
<label htmlFor="email">Email: </label>
<input
type="text"
name="email"
id="email"
className={classNames("form-control",{"is-invalid":errors.email,})}
placeholder="email#example.com"
autoComplete="off"
{...register('email',
{
required: true,
pattern:/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/,
})
}
/>
<span id="mail" className="text-danger fw-bold">{errors.email?.type === "required" && "Email is required"}</span>
<span id="mail" className="text-danger fw-bold">{errors.email?.type === "pattern" &&"Invalid format"}</span>
</div>
<input type="submit" id="submit" value="submit" onClick={postData} className="btn btn-success my-3" />
</form>
That is code which I try but it not working anybody review it and give your valuable comments and suggestions
Basically I want form validation using react hook form,its done but when I stuck in passing data to fire base data base
when I use, useState then its override because react hook form already store it but how to pass it to data base with out useState??
Through react hook form
You should remove your onClick from the submit button and handle your form submission from the onSubmit event on the form. Send your form data to your firebase endpoint, from your onSubmit function like so.
<input type="submit" id="submit" value="submit" onClick={postData} <-- Remove this
className="btn btn-success my-3" />
...
const onSubmit = (data) => {
// All your form fields will the converted to json object (data)
// and will be handled by hooks form
console.log(data);
// send data to firebase API
const responseRaw = fetch(
"https://your-firebase-url",
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}
);
const response = responseRaw.json();
};
When I run the code the buttons don't work unless I take out onChange. I can add () to the end of my functions inside the on click but that makes them run on every key stroke. How do I fix this. It wont't let me post my question without more text so I am going to add some dummy text to post.
import React, { useState } from "react";
export default function Username(props) {
const [userName, setUsername] = useState('');
let userToken
const address = props.address;
function handleChange(event) {
setUsername(event.target.value);
}
function loginAccount() {
console.log('account created');
}
function createAccount() {
console.log('logged in');
}
function hi(){
console.log('hi');
}
while (userToken == null)
return (
<>
<div>
<p className = "account-Info" >address: {address}</p>
</div>
<div id="form">
<h2 className='user-Create' > Username </h2>
<form id='set-User'>
<input id='username' className="user-Create" type='text' value={userName} onChange={handleChange}
required minLength='3' maxLength='30' pattern="[a-zA-Z0-9_]+" title='only letters, numbers, and underscores.'/>
<button className='user-Create' onClick={loginAccount}>Create Account</button>
<button className='user-Create' onClick={createAccount}>Login</button>
<button className='user-Create' onClick={hi}>hi</button>
</form>
</div>
</>
);
while (userToken)
return(
<p>hello</p>
);
}
Set type="button" for each button inside your form
<button className='user-Create' type="button" onClick={loginAccount}>Create Account</button>
<button className='user-Create' type="button" onClick={createAccount}>Login</button>
<button className='user-Create' type="button" onClick={hi}>hi</button>
format like this
const FunctionName = (e) => {
console.log('account created');
I hope you are doing great, I am using Emailjs in React to get Emails. I configure Emailjs and it is properly sending test Emails but when I am trying to send from my project so it's not sending and even it is also not showing any error
Here is the template of the Email
Here is the ID and token which I hide but I am just showing this image to explain
clearly
(1) Here i import emailjs
import emailjs from '#emailjs/browser';
(2) Here is the function that will send the email, (Here in the fourth parameter I am just showing 5 characters as I hide in the above image )
function sendEmail(e) {
e.preventDefault();
emailjs.send('gmail', 'zaryabkhan864', e.target, 'G5CpT9*******')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
e.target.reset()
}
(3) Here is the Form code
<form onSubmit={sendEmail}>
<div className="mb-3">
<label htmlFor="name" className="form-label">Your Name</label>
<input type="text" className="form-control" id="name" placeholder="Muhammad Zaryab Khan" name="name" />
</div>
<div className="mb-3">
<label htmlFor="email" className="form-label">Email address</label>
<input type="email" className="form-control" id="exampleFormControlInput1" placeholder="name#example.com" name="email" />
</div>
<div className="mb-3">
<label htmlFor="exampleFormControlTextarea1" className="form-label">Your Message</label>
<textarea className="form-control" id="Message" rows="5" name="message"></textarea>
</div>
<button type="submit" className="btn-theme">Send Message <i className="fa fa-paper-plane ms-2"></i></button>
</form>
Now I am receiving this error
add ref atribute for form, and ad useRef
const form = useRef<HTMLFormElement>(null);
after you should change e.target => form.current
const form = useRef();
const sendEmail = (e) => {
e.preventDefault();
emailjs.sendForm('service_id', 'template_id', form.current, 'user_id')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
alert("Email Send");
};
so i have this form that updates some user information, but when i click the cancel button it behaves like i clicked update which is the submit button,ive had this happen on another form but i figured out how to reset the input values so its the same as the default values. here is the code im using:
const emailRef = useRef();
const passwordRef = useRef();
const confirmPasswordRef = useRef();
function handleSubmit(e) {
e.preventDefault();
if (confirmPasswordRef.current.value !== passwordRef.current.value) {
return setAlert("password do not match");
}
const promises = [];
setLoading(true);
setAlert("");
if (emailRef.current.value !== currentUser.email) {
promises.push(updateEmail(emailRef.current.value));
}
if (passwordRef.current.value) {
promises.push(updatePassword(passwordRef.current.value));
}
if (usernameRef.current.value !== currentUser.displayName) {
promises.push(updateUsername(usernameRef.current.value));
}
Promise.all(promises)
.then(() => {
setAlert("update complete");
})
.catch(() => {
setAlert("failed to update profile");
})
.finally(() => {
setLoading(false);
});
}
<form onSubmit={handleSubmit} className="update-profile-form">
<label className="label">Email</label>
<div className="input-container">
<input
defaultValue={currentUser.email}
ref={emailRef}
type="text"
required
></input>
</div>
<label className="label">Password</label>
<div className="input-container">
<input
ref={passwordRef}
type="text"
></input>
</div>
<label className="label">Confirm Password</label>
<div className="input-container">
<input
ref={confirmPasswordRef}
type="text"
></input>
</div>
<div className="update-profile-buttons-div">
<button
className="cancel-button"
>
Cancel
</button>
<button
disabled={loading}
type="submit"
>
Update
</button>
</div>
</form>
I need to implement a clear/reset for the inputs after onClick occurs, and also after it is stored in localStorage. I can't seem to figure out how to code this and where. Here is my add function and render function.
addExpense(e) {
e.preventDefault()
let exList = this.state.exList
if (this.state.expense === null) {
alert('Please enter a name.')
return false
}
if (this.state.amount === 0) {
alert('Please enter a valid amount.')
return false
}
if(isNaN(this.state.amount)) {
alert('The amount must be a number.')
return false
}
this.state.exList.push({ 'title':this.state.title, 'amount':this.state.amount })
this.setState({ exList: this.state.exList })
localStorage.setItem('exList', JSON.stringify(exList))
}
render() {
let myExpenses = this.state.exList.map((val, key) => { return <ExpenseList val={val} key={key} id={key} delMe={() =>this.removeExpense(key) } />
})
return (
<main className="ContactList">
<section className="add container">
<h2 className="newExpense">Add Expense</h2>
<form name="myForm">
<p>
<label>Title </label>
<input type="text" name="title" onChange= .
{this.changeExpense} />
<label>Amount </label>
<input type="text" name="amount" onChange= .
{this.changeAmount} />
<button type="submit" className="btn" onClick= .
{this.addExpense}>Add</button>
</p>
</form>
</section>
<section className="container">
<h3 className="currentExpense">Current Expenses</h3>
<article className="contentScroll">
<ul className="expenseCont">{myExpenses}</ul>
</article>
</section>
</main>
)
}
In react everything depends on your state, If the value of a state field changed then your page again render by react
So if you want to clear all the fields of your form then you have to clear the object associated with your text.
Like I set an object in the state within the construction of a component like
this.setState({name: '', email: '', phone_number: ''});
Now after some operation, all the field in my state has values. Now I want clear all the fields after click a button clear, then I will make a function for the clear button and I will write following code inside the clear function
const clear_obj = Object.assign({},this.state);
for(let key in clear_obj){
clear_obj[key] = '';
}
this.setState(clear_obj);
I can also set the default values so that It will look fresh form.
You need to have the value attribute for inputs
value={this.state.expense}
and
value={this.state.amount}
in changeExpense and changeAmount you need to set the state with new value.
to clear inputs, in addExpense below localStorage call you need to setState again
this.setState({ expense: '', amount: '' })
Your code would look like this.
addExpense(e) {
e.preventDefault()
let exList = this.state.exList
if (this.state.expense === null) {
alert('Please enter a name.')
return false
}
if (this.state.amount === 0) {
alert('Please enter a valid amount.')
return false
}
if(isNaN(this.state.amount)) {
alert('The amount must be a number.')
return false
}
this.state.exList.push({ 'title':this.state.title, 'amount':this.state.amount })
localStorage.setItem('exList', JSON.stringify(exList))
this.setState({ expense: '', amount: '', exList: this.state.exList });
}
render() {
let myExpenses = this.state.exList.map((val, key) => { return <ExpenseList val={val} key={key} id={key} delMe={() =>this.removeExpense(key) } />
})
return (
<main className="ContactList">
<section className="add container">
<h2 className="newExpense">Add Expense</h2>
<form name="myForm">
<p>
<label>Title </label>
<input type="text" name="title" value={this.state.expense} onChange= .
{this.changeExpense} />
<label>Amount </label>
<input type="text" name="amount" value={this.state.amount} onChange= .
{this.changeAmount} />
<button type="submit" className="btn" onClick= .
{this.addExpense}>Add</button>
</p>
</form>
</section>
<section className="container">
<h3 className="currentExpense">Current Expenses</h3>
<article className="contentScroll">
<ul className="expenseCont">{myExpenses}</ul>
</article>
</section>
</main>
)
}
If you're just trying to clear some form fields, you could set the state for each field after submission to ''.
For example:
this.setState({
amount: '',
exList: ''
});
You would add this after all of your data has been saved and processed, so at the end of your function would be ok. Or, you could create another function to handle clearing each form field.