My react form is not submitting correctly - reactjs

i have a problem with my react's form.
If I click twice on the submit button then at this moment, the form submits correctly and sends my various information to the database.
Where is the problem ?
import React, { useState } from 'react';
import axios from 'axios';
const Register = () => {
const [username, setUsername] = useState();
const [password, setPassword] = useState();
const onSubmit = (e) => {
e.preventDefault();
setUsername(document.querySelector(".usernameInput").value);
setPassword(document.querySelector(".passwordInput").value);
const user = {
username: username,
password: password
}
axios.post('http://localhost:5000/users/add', user)
.then(res => console.log(res.data));
console.log("lancement du formulaire");
}
return (
<div>
<h1>TEST Form</h1>
<form onSubmit={onSubmit}>
<div className="form-group">
<label>Username</label>
<input required type="text" className="usernameInput" />
</div>
<div className="form-group">
<label>Password</label>
<input required type="password" />
</div>
<div className="form-group">
<input type="submit" value="Create User" className="btn btn-primary" className="passwordInput" /> </div>
</form>
</div>
)
}
export default Register;
Thanks .

useState is asynchronous just like setState in class components. You can't update the state on one line and assume it's already changed on the next one. You'll likely use the unchanged state.
When you create the user object, the state is not yet updated.
You need to click twice on the submit button because:
on the first click you set the username and password states' value to the input value but as the state is not updated, you send the user objects with empty properties
on the second click (when the state is updated) you can send the user object, as the user object contains the state values
The following should work (though I would recommend not to use it):
const onSubmit = (e) => {
e.preventDefault();
const user = {
username: document.querySelector('.usernameInput').value,
password: document.querySelector('.passwordInput').value,
};
axios
.post('http://localhost:5000/users/add', user)
.then((res) => console.log(res.data));
console.log('lancement du formulaire');
};
But why do you use states username and password if you never use them? If you've already added the states to store the input values, you can update them on changes and submit them on form submit:
const Register = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const onSubmit = (e) => {
e.preventDefault();
const user = {
username,
password,
};
axios
.post('http://localhost:5000/users/add', user)
.then((res) => console.log(res.data));
console.log('lancement du formulaire');
};
return (
<div>
<h1>TEST Form</h1>
<form onSubmit={onSubmit}>
<div className="form-group">
<label>Username</label>
<input
required
type="text"
className="usernameInput"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div className="form-group">
<label>Password</label>
<input
required
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="form-group">
<input
type="submit"
value="Create User"
className="btn btn-primary"
className="passwordInput"
/>{' '}
</div>
</form>
</div>
);
};

Related

Supabase signup with react state email and password

I am trying to implement the standard Supabase signup, using react-jsx, but keep getting the response:
"You must provide either an email or phone number and a password"
My code looks as follows:
const [login, setLogin] = useState('')
const [password, setPassword] = useState('')
const signUpSubmitted = () => {
supabase.auth
.signUp({ login, password })
.then((response) => {response.error ? alert(response.error.message) : setToken(response)})
.catch((err) => { alert(err)})
}
and the form:
<form id='sign-up'>
<h3>Sign Up</h3>
<label>Email:</label>
<input
type='email'
value={login}
onChange={(e) => setLogin(e.target.value)}
/>
<label>Password:</label>
<input
type='password'
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<input onClick={signUpSubmitted} type='submit'/>
</form>
I assume the problem lies with me attempting to save the values in a state, before passing them to the database. I don't see why it should be a problem, they are both strings from what I understand, so maybe I'm way off.
According to the Supabase docs, you need to pass email instead of login.
const { data, error } = await supabase.auth.signUp({
email: 'example#email.com',
password: 'example-password',
})
I would also suggest a few other optimizations:
Move your submit handler to the <form /> in order to support submitting the form with the Enter key.
Add event.preventDefault() to your submit handler to prevent the default form browser redirection behavior.
Change your submit input to a more semantic <button />.
Link your labels and inputs together with htmlFor and id attributes for accessibility (just make sure they're unique ids).
Updated Component:
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [token, setToken] = useState();
const handleSubmit = (event) => {
event.preventDefault();
supabase.auth
.signUp({ email, password })
.then((response) => {
response.error ? alert(response.error.message) : setToken(response)
})
.catch((err) => { alert(err) });
}
return (
<form id="sign-up" onSubmit={handleSubmit}>
<h3>Sign Up</h3>
<label htmlFor="email">Email:</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<label htmlFor="password">Password:</label>
<input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit">Sign Up</button>
</form>
);

Fields tied to the state doesn't clear on successful form submission

I have a contact form, when the form submission is successful it should clear the form field name, email and message which is tied up to the state. The form submission is successful but form fields name, email and message doesn't clear.
For test purpose what I'm doing is passing default values to the state but this values doesn't get filled in form during initial load.
export default function Contact() {
const [name, setName] = useState('John Doe')
const [email, setEmail] = useState('me#example.com')
const [message, setMessage] = useState('Hello, this is test message.')
const onSubmit = (e) => {
e.preventDefault()
const form = {"name": name, "email": email, "message": message}
return fetch('/api/contact', {
method: 'POST',
body: JSON.stringify(form),
headers: {'Content-Type': 'application/json'}
}).then(response => {
if(response.status === 200){
setName('')
setEmail('')
setMessage('')
} else {
}
}).catch(err => err)
}
return (
<section>
<form method='post'>
<div>
<label>Name</label>
<input type="text" name="name" onChange={(e) => {setName(e.target.value)}}/>
</div>
<div>
<label>Email Address</label>
<input type="email" name="email" onChange={(e) => {setEmail(e.target.value)}}/>
</div>
<div>
<label>Message</label>
<textarea minLength={5} maxLength={2000} rows="6" name="message" onChange={(e) => {setMessage(e.target.value)}}></textarea>
</div>
<div>
<button type='submit' onClick={(e) => {onSubmit(e)}}>Send Message</button>
</div>
</form>
</section>
);
}
As User456 said, you need to add value={variable} for every <input />.
Example:
import { useState } from "react";
export default function Contact() {
const [name, setName] = useState("John Doe");
const [email, setEmail] = useState("me#example.com");
const [message, setMessage] = useState("Hello, this is test message.");
const onSubmit = (e: any) => {
e.preventDefault();
setName("");
setEmail("");
setMessage("");
};
return (
<section>
<form method="post">
<div>
<label>Name</label>
<input
type="text"
name="name"
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
</div>
<div>
<label>Email Address</label>
<input
type="email"
name="email"
value={email}
onChange={e => {
setEmail(e.target.value);
}}
/>
</div>
<div>
<label>Message</label>
<textarea
minLength={5}
maxLength={2000}
name="message"
value={message}
onChange={e => {
setMessage(e.target.value);
}}></textarea>
</div>
<div>
<button
type="submit"
onClick={e => {
onSubmit(e);
}}>
Send Message
</button>
</div>
</form>
</section>
);
}

React js firebase empty field validation

I have created a form in react and store the details in firebase but my problem is even if the feilds are empty the form is submitted, i want validation that feild should not be empty if the user wants to submit.
const Account2 = () => {
const [kookid, setKookID] = useState("");
const [kookname, setKookName] = useState("");
const userCollectionRef = collection(db, "mastermenu")
const handleSubmit = () => {
addDoc(userCollectionRef,{
kookid: kookid,
kookname: kookname,
}).then(() => {
if(!alert("form Submitted Successfully!!!"));
navigate("/account");
})
return (
<><div className='outer-container'>
<h1 className='text-3xl font-bold py-2'>MASTER MENU</h1>
</div>
<div className='outer-container'>
<form className='contactform'>
<label>Kook ID</label>
<input
placeholder=""
onChange={(e) => setKookID(e.target.value) } />
<label>Kook Name</label>
<input
required
placeholder=""
onChange={(e) => setKookName(e.target.value)} />
</form>
<button onClick={handleSubmit}>Submit</button>
</div></>
)
}

Change multiple elements simultaneously

I have a button which upon clicking, should make the password field blank. I also intend to change the text of the button from Change Password to Save password at the same time. In short, I would like these changes to happen at the same time. I have taken a toggle variable using which I'm able to change the text of the button but do not know how to do the same for the password field.
Here is my code:
import { useState } from "react";
import { useHistory } from "react-router";
const User = () => {
const [username, setUsername] = useState()
const [password, setPassword] = useState()
const [toggle, setToggle] = useState(false);
const history = useHistory();
const login = () => {
// if (username === 'admin' & password === 'admin') {
// history.push('/home')
// } else {
// alert('wrong credentials')
// }
setToggle(!toggle);
}
return (
<>
<div className="container">
<label for="username">UserName:</label>
<input
className="form-control"
type='text'
id="username"
name="username"
value={username}
onChange={(evt) => setUsername(evt.target.value)}
/>
<br />
<label for="password">Password:</label>
<input
className="form-control"
type='text'
id="password"
name="password"
value={password}
onChange={(evt) => setPassword(evt.target.value)}
/>
<button className="btn btn-primary mt-5 " onClick={login}>{toggle ? 'SavePassword' : ' change password '}</button>
<button className="btn btn-primary mt-5 ml-5 pull-right" onClick={login}>Log out</button>
</div>
</>
)
}
export default User;
Fastest answer is:
const login = () => {
setPassword('');
setToggle(!toggle);
}
This solution has a problem: every time you run login function your component is re-rendered twice.
To avoid this, there are several ways; the first one could be join username, password and toggle into the same state. Something like:
const [state, setState] = useState({
username: null,
password: null,
toggle: false
});
...
const login = () => {
setState((prevState) => {
return {
toggle: !prevState.toggle,
username: prevState.username
password: "",
}
});
}

update input of user in map function React hooks

New to react hooks...
I've brought some data of users from an API and I want to update one or more of the inputs by clicking a submit button.
I can see in the state that the user's last letter changes but I can see the new input on the screen and I can not change the entire word. And I don't know if it is supposed to change also in the whole array of users or it is impossible once I've called them from the API.
Thanks
import { useState } from 'react'
import axios from 'axios'
function UsersComp() {
const [user, setUser] = useState()
const [users, setUsers] = useState([])
const [id, setId] = useState(0)
const getUsers=async ()=>{
let resp = await axios.get("https://jsonplaceholder.typicode.com/users")
setUsers(resp.data);
}
const update = async (e) =>
{
e.preventDefault();
let resp = await axios.put("https://jsonplaceholder.typicode.com/users/" + id, user)
}
return (
<div calssname="App">
<form onSubmit={e => update(e)}>
{
users.map((item) =>
{
return <tbody key={item.id}>
<tr><td>
ID:{item.id} <br/>
Name:<input value={item.name} onChange={e => setUser({...user, name : e.target.value})} type="text" name="name" /> <br/>
Email:<input value={item.email} onChange={e => setUser({...user, email : e.target.value})} type="text" name="email" /> <br/>
<input type="button" value="Add Data"/>
<input type="submit" value="Update"/>
<input type="button" value="Delete"/><br/>
</td></tr>
</tbody>
})
}
</form>
<input type="button" value="Get users" onClick={getUsers} /> <br/>
</div>
);
}
export default UsersComp;
You can update onChange like this by using map:
onChange={(e) =>
setUser(
users.map((eachUser) =>
item.id === eachUser.id ? { ...eachUser, name: e.target.value } : eachUser,
),
)
}

Resources