have that problem with resetting the values of the input fields in the form. and wanted to ask if somebody knows a better and way to do that instead of just making 'useState' for every field...
const handleSubmit = (e) => {
e.preventDefault();
emailjs.sendForm('sample_id', 'someother_id', formRef.current, 'user_is')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
setMessage(true);
setEmail("");
setName("");
setSubject("");
setTextarea("");
};
return (
<div className="contact" id="contact">
<div className="left">
<img src="" alt="" />
</div>
<div className="right">
<h2>Kontakt</h2>
<form ref={formRef} onSubmit={handleSubmit}>
<label>Name</label>
<input onChange={(e) => setName(e.target.value)} type="text" placeholder="Name" name="user_name" value={name} />
<label>Email</label>
<input onChange={(e) => setEmail(e.target.value)} type="email" placeholder="Email" name="user_email" value={email} />
<label>Betreff</label>
<input onChange={(e) => setSubject(e.target.value)} type="text" placeholder="Subject" name="user_subject" value={subject} />
<label>Nachricht</label>
<textarea onChange={(e) => setTextarea(e.target.value)} placeholder="Message" name="message" value={textarea} />
<button type="submit">Send</button>
{message && <span>Thanks we will respond ASAP.</span>}
</form>
</div>
</div>
)
}
You could use a single state for all the form values (kinda like we did before functional components)
// this could be outside your component
const initialState = { email: "", name: "", subject: "", textArea: ""};
// declaring your state
const [formState, setFormState] = React.useState(initialState);
and then
const handleSubmit = (e) => {
e.preventDefault();
emailjs.sendForm('sample_id', 'someother_id', formRef.current, 'user_is')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
setMessage(true);
setFormState(initialState)
};
You also would have to rewrite your input handlers. Like that :
<input onChange={(e) => setFormState({...formState, name: e.target.value})} type="text" placeholder="Name" name="user_name" value={name} />
Related
i a new user and a new in React world. I need help to solve this situation about a Select with values from mysql DB.
I receive the values, but the select goes in infinite loop.
The error is surely in this file cause server.js works without problem!!
Really thanks for the help, and sorry if it could be a stupid question. I m studying react from one week and i have not found answers on internet
function FormAddMenu({ registerMenu }) {
const [nomeMenuReg, setNomeMenuReg] = useState("");
const [descrizioneMenuReg, setDescrizioneMenuReg] = useState("");
const [prezzoMenuReg, setPrezzoMenuReg] = useState("");
const [disponibilitaMenuReg, setDisponibilitaMenuReg] = useState("");
const [portataMenuReg, setPortataMenuReg] = useState("");
const [addMenu, setAddMenu] = useState({
portataMenuReg: "",
nomeMenuReg: "",
descrizioneMenuReg: "",
prezzoMenuReg: "",
disponibilitaMenuReg: "",
});
const [portate, setPortate] = useState({ value: "", label: "" });
const selectOptions = async () => {
Axios.post("http://localhost:3001/selectPortata").then((response) => {
// console.log("risposta:",response.data)
setPortate(
response.data.map((risp) => ({
...setPortate,
value: risp.value,
label: risp.label,
})),
);
});
};
selectOptions();
console.log("portate:", portate);
const submitHandler = (e) => {
e.preventDefault();
registerMenu(addMenu);
document.getElementById("addmenu").reset();
};
const handleCheckbox = (e) => {
console.log(e.target.checked);
if (e.target.checked === true) {
setAddMenu({ ...addMenu, disponibilitaMenuReg: 1 });
} else {
setAddMenu({ ...addMenu, disponibilitaMenuReg: e.target.value });
}
};
return (
<div className="container width85">
<h1>CREA IL MENU'</h1>
<form id="addmenu">
<div className="mb-3">
<label htmlFor="portataMenuReg" className="form-label">
PORTATA
</label>
<Select
options={portate}
onChange={(e) => setAddMenu({ ...addMenu, portataMenuReg: e.target.value })}
className="mb-3"
/>
</div>
<div className="mb-3">
<label htmlFor="nomeMenuReg" className="form-label">
NOME
</label>
<input
type="text"
onChange={(e) => setAddMenu({ ...addMenu, nomeMenuReg: e.target.value })}
className="form-control"
id="nomeMenuReg"
rows="3"
/>
</div>
<div className="mb-3">
<label htmlFor="descrizioneMenuReg" className="form-label">
DESCRIZIONE
</label>
<textarea
className="form-control"
onChange={(e) =>
setAddMenu({ ...addMenu, descrizioneMenuReg: e.target.value })
}
id="descrizioneMenuReg"
rows="3"
></textarea>
</div>
<div className="mb-3">
<label htmlFor="prezzoMenuReg" className="form-label">
PREZZO
</label>
<input
type="text"
className="form-control"
onChange={(e) => setAddMenu({ ...addMenu, prezzoMenuReg: e.target.value })}
id="prezzoMenuReg"
rows="3"
/>
</div>
<div className="mb-3">
<label htmlFor="disponibilitaMenuReg" className="form-label">
DISPONIBILITA'
</label>
<input
type="checkbox"
value="0"
className="htmlForm-control"
onChange={handleCheckbox}
id="disponibilitaMenuReg"
rows="3"
/>
</div>
<div className="mb-3">
<button type="submit" onClick={submitHandler} className="btn btn btn-danger">
AGGIUNGI AL MENU
</button>
</div>
</form>
</div>
);
}
export default FormAddMenu;
Wrap the selectOptions(); call in an useEffect (since loading data and mutating state based on it is a side effect).
The empty dependency array (documented above) means the effect is only executed once on mount.
React.useEffect(() => {
selectOptions();
}, []);
import React,{ useState} from 'react';
import { Button, Checkbox, Form } from 'semantic-ui-react';
import axios from 'axios';
const Create = () => {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [checkbox, setCheckBox] = useState(false);
Here I am sending data to a mock api I created
const postData = () =>{
axios.post(`https://61cb2af8194ffe0017788c01.mockapi.io/fakeData`,{
firstName,
lastName,
checkbox
})
}
This is the method I created to reset the form but it does not work.
const resetForm = () => {
postData();
setFirstName(" ");
setLastName(" ");
setCheckBox(false);
}
This is my form where on click i am calling resetForm function but it is not resetting it
is sending the data but not resetting the form.
return(
<div>
<Form>
<Form.Field>
<label>First Name</label>
<input id="f1" placeholder='First Name' onChange={(e)=>setFirstName(e.target.value) } />
</Form.Field>
<Form.Field>
<label>Last Name</label>
<input id="last1" placeholder='Last Name' onChange={(e)=>setLastName(e.target.value)}/>
</Form.Field>
<Form.Field>
<Checkbox id="c1" label='I agree to the Terms and Conditions' onChange={(e)=>setCheckBox(!checkbox)}/>
</Form.Field>
<Button type='submit' onClick={resetForm}>Submit</Button>
</Form>
<br></br>
<Button onClick={()=>navigate(-1)}>Go Back</Button>
</div>
)
}
export default Create;
Actually it will reset the form, the problem is you do not use Controlled Components to show the latest update value in UI
you should bind the value like this:
<input type="text" value={this.state.value} onChange={this.handleChange} />
You can refer the doc here:
https://reactjs.org/docs/forms.html
You can reset your form using the native form.reset() method.
const Create = () => {
const ref = React.useRef(null);
const resetForm = () => ref.current.reset();
return (
<div>
<Form ref={ref}>
<Form.Field>
<label>First Name</label>
<input id="f1" placeholder="First Name" onChange={(e) => setFirstName(e.target.value)} />
</Form.Field>
<Form.Field>
<label>Last Name</label>
<input id="last1" placeholder="Last Name" onChange={(e) => setLastName(e.target.value)} />
</Form.Field>
<Form.Field>
<Checkbox
id="c1"
label="I agree to the Terms and Conditions"
onChange={(e) => setCheckBox(!checkbox)}
/>
</Form.Field>
<Button type="submit" onClick={resetForm}>
Submit
</Button>
</Form>
<br></br>
<Button onClick={() => navigate(-1)}>Go Back</Button>
</div>
);
};
export default Create;
For that, you have to set value property in your input. Try this
const Create = () => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [checkbox, setCheckBox] = useState(false);
const postData = () => {
console.log(firstName, lastName, checkbox);
};
const resetForm = () => {
postData();
setFirstName(" ");
setLastName(" ");
setCheckBox(false);
};
return (
<div>
<Form>
<Form.Field>
<label>First Name</label>
<input
id="f1"
placeholder="First Name"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
</Form.Field>
<Form.Field>
<label>Last Name</label>
<input
id="last1"
placeholder="Last Name"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
</Form.Field>
<Form.Field>
<Checkbox
id="c1"
label="I agree to the Terms and Conditions"
checked={checkbox}
onChange={(e) => setCheckBox(!checkbox)}
/>
</Form.Field>
<Button type="submit" onClick={resetForm}>
Submit
</Button>
</Form>
</div>
);
};
i want to validate my form by checking if all the fields are filled. I am quite new to react. Any suggestions? I have got the states ready, but i am pretty much stuck. Thank you in advance for your replies. I appreciate it
my code:
const [fields, setFields] = useState({
name: '',
email: '',
subject: '',
msg: '',
});
const handleSubmit = (event) => {
emailjs.sendForm().then(
(result) => {
console.log(result.text);
},
(error) => {
console.log(error.text);
}
);
alert('form submitted');
event.target.reset();
event.preventDefault();
};
<form onSubmit={handleSubmit}>
<div className={styles.firstInputs}>
<div>
<label>name</label>
<br />
<input
type='text'
refs='name'
name='name'
placeholder='your name'
></input>
</div>
<div>
<label>email</label>
<br />
<input type='email' name='email' placeholder='email'></input>
</div>
</div>
<label>subject</label>
<br />
<input
type='text'
name='subject'
placeholder='subject'
className={styles.subject}
></input>{' '}
<br />
<label>message</label> <br />
<textarea placeholder='your message' name='message'></textarea>
<br />
<button type='submit' className={styles.sendForm}>
SUBMIT
</button>
</form>;
You are not using your state correctly there.
Set the values of the fields to what is in the state, then change the state when the fields change.
Don't forget you can just add the required attribute to your HTML element to make sure it gets some kind of value.
Then you just validate the state before submission.
Don't just fall back on packages all the time as people suggest here. As you say, you are new to React so, learn to set things up manually (which is basically less work for small forms). Once you understand that, then consider if having another dependency is really saving you time.
See sample code below in action here: https://codesandbox.io/s/form-validation-pbbf1
import { useState } from "react";
import "./styles.css";
const defaultFields = { name: "", email: "", subject: "", message: "" };
export default function App() {
const [fields, setFields] = useState(defaultFields);
const handleSubmit = (event) => {
// Stop form from resetting
event.preventDefault();
// Check fields
if (fields.name.length < 2) {
return alert("Name should be greater than 1 character.");
}
// etc...
// Send off data
/*
emailjs.sendForm().then(
(result) => {
console.log(result.text);
},
(error) => {
console.log(error.text);
}
);
*/
// I would probably put these two
// lines inside the then block above.
setFields(defaultFields);
alert("form submitted");
};
const handleFieldChange = (e) => {
const { name, value } = e.target;
setFields((previousFields) => ({ ...previousFields, [name]: value }));
};
return (
<form onSubmit={handleSubmit}>
{/* NAME */}
<div>
<label>name</label>
<br />
<input
type="text"
name="name"
placeholder="your name"
value={fields.name}
required
onChange={handleFieldChange}
></input>
</div>
{/* EMAIL */}
<div>
<label>email</label>
<br />
<input
type="email"
name="email"
placeholder="email"
value={fields.email}
required
onChange={handleFieldChange}
></input>
</div>
{/* SUBJECT */}
<div>
<label>subject</label>
<br />
<input
type="text"
name="subject"
placeholder="subject"
value={fields.subject}
required
onChange={handleFieldChange}
></input>{" "}
<br />
</div>
{/* MESSAGE */}
<div>
<label>message</label> <br />
<textarea
placeholder="your message"
name="message"
value={fields.message}
required
onChange={handleFieldChange}
></textarea>
</div>
<button type="submit">SUBMIT</button>
</form>
);
}
I've been trying to console.log these 2 inputs, but can't seem to figure it out, can anyone tell me what I've done wrong?
I keep getting the Cannot read property 'value' of null error
function printInputs() {
let username = document.getElementById('user').value
let password = document.getElementById('pass').value
console.log(username);
console.log(password);
}
function App() {
return (
<div className="App">
<h1>Log In</h1>
<h1>{code}</h1>
<form>
<input className='userInput' id='user' type='text' placeholder='username' /><br />
<input className='userInput' id='pass' type='password' placeholder='password' /><br />
<input className='userSubmit' type='submit' value='Log In' onSubmit={printInputs()} />
</form>
</div>
);
}
onSubmit={printInputs()}
You are trying to call printInputs immediately (before the render function has returned anything so before the inputs are in the page).
You need to pass a function to onSubmit:
onSubmit={printInputs}
That said, this is not the approach to take for getting data from forms in React. See the Forms section of the React guide for the right approach.
The way to write forms in react. Working example demo
function App() {
const [state, setState] = React.useState({ username: "", password: "" });
const handleSubmit = e => {
e.preventDefault();
console.log(state);
};
const handleChange = e => {
setState({
...state,
[e.target.name]: e.target.value
});
};
return (
<div className="App">
<h1>Log In</h1>
<form onSubmit={handleSubmit}>
<input
className="userInput"
name="username"
type="text"
placeholder="username"
onChange={handleChange}
/>
<br />
<input
className="userInput"
name="password"
type="password"
placeholder="password"
onChange={handleChange}
/>
<br />
<input className="userSubmit" type="submit" value="Log In" />
</form>
</div>
);
}
in the first never use real dom to manipulate the dom in
React ,use a state to get de value and the onSumbit is used in Form tag
import React, { useState } from "React";
const App = () => {
const [userName, setUserName] = useState("");
const [password, setPassword] = useState("");
const printInputs = () => {
console.log(userName);
console.log(password);
};
return (
<div className="App">
<h1>Log In</h1>
<form onSubmit={printInputs}>
<input
className="userInput"
id="user"
type="text"
placeholder="username"
onChange={event => setUserName(event.target.value)}
/>
<br />
<input
className="userInput"
id="pass"
type="password"
placeholder="password"
onChange={event => setPassword(event.target.value)}
/>
<br />
<input
className="userSubmit"
type="submit"
value="Log In"/>
</form>
</div>
);
};
export default App;
I'm building a simple website with Gatsby. The website has a form which contains some input fields type text and one input type file.
I'm using styled-component.
const initialState = {
firstName: "",
lastName: "",
email: "",
phoneNumber: "",
message: "",
cv: null,
linkedinUrl: "",
isSent: false,
validation: validator.valid(),
}
const [formData, setFormData] = useState({
...initialState,
})
const [isFormSubmitted, setIsFormSubmitted] = useState(false)
const handleInputChange = event => {
setFormData({
...formData,
[event.target.name]: event.target.value,
})
}
const handleFileLoad = e => {
setFormData({
...formData,
cv: e.target.files[0],
})
}
const handleSubmit = event => {
event.preventDefault()
// const { firstName, lastName, email, phoneNumber, siteWeb, message } = formData
const validation = validator.validate(formData)
setFormData({
...formData,
validation,
})
setIsFormSubmitted(true)
if (validation.isValid) {
const encode = data => {
console.log(data)
return Object.keys(data)
.map(
key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key])
)
.join("&")
}
fetch(event.target.action, {
method: "POST",
headers: { "Content-Type": "multipart/form-data" },
body: encode({ "form-name": title, job, ...formData }),
})
.then(() => setFormData({ ...initialState, isSent: true }))
.catch(error => alert(error))
}
}
const {
firstName,
lastName,
email,
phoneNumber,
linkedinUrl,
message,
validation,
} = formData
// if the form has been submitted at least once, then check validity every time we render
// otherwise just use what's in state
const copyData = { ...formData }
const formValidation =
isFormSubmitted && !formData.isSent
? validator.validate(copyData)
: validation
return (
<FormStyled
onSubmit={handleSubmit}
data-netlify="true"
name={title}
method="POST"
netlify-honeypot="bot-field"
>
<Spacer flex="1 1 50%">
<Input
type="text"
placeholder="Prénom"
value={firstName}
handleChange={e => handleInputChange(e)}
name="firstName"
required
fullWidth
id="firstName"
/>
<input type="hidden" name="form-name" value={title} />
<input
type="text"
value={job}
name="job"
id="job"
style={{ display: "none" }}
/>
<ValidationMessage isInvalid={formValidation.firstName.isInvalid}>
{formValidation.firstName.message}
</ValidationMessage>
</Spacer>
<Spacer flex="1 1 50%">
<Input
type="text"
placeholder="Nom"
value={lastName}
handleChange={e => handleInputChange(e)}
name="lastName"
required
fullWidth
id="lastName"
/>
<ValidationMessage isInvalid={formValidation.lastName.isInvalid}>
{formValidation.lastName.message}
</ValidationMessage>
</Spacer>
<Spacer flex="1 1 50%">
<Input
type="tel"
placeholder="Téléphone"
value={phoneNumber}
handleChange={e => handleInputChange(e)}
name="phoneNumber"
fullWidth
id="phoneNumber"
/>
<ValidationMessage isInvalid={formValidation.phoneNumber.isInvalid}>
{formValidation.phoneNumber.message}
</ValidationMessage>
</Spacer>
<Spacer flex="1 1 50%">
<Input
type="email"
placeholder="E-mail"
value={email}
handleChange={e => handleInputChange(e)}
name="email"
required
fullWidth
id="email"
/>
<ValidationMessage isInvalid={formValidation.email.isInvalid}>
{formValidation.email.message}
</ValidationMessage>
</Spacer>
<Spacer flex="1 1 auto">
<Button title="Télécharger votre CV" colors="primary">
<InputFile type="file" id="cv" onChange={handleFileLoad} name="cv" />
</Button>
</Spacer>
<Spacer flex="1 1 auto">
<Text>et / ou</Text>
</Spacer>
<Spacer className="linkedin-url">
<Input
type="url"
placeholder="Lien de votre profil linkedin"
value={linkedinUrl}
handleChange={e => handleInputChange(e)}
name="linkedinUrl"
required
fullWidth
id="linkedinUrl"
iconLeft={
<LogoLinkedin>
<img src={Lkd} alt="lien Linkedin" />
</LogoLinkedin>
}
></Input>
</Spacer>
<Spacer>
<Textarea
type="text"
placeholder="Votre message..."
value={message}
handleChange={e => handleInputChange(e)}
name="message"
required
fullWidth
id="message"
/>
<ValidationMessage isInvalid={formValidation.message.isInvalid}>
{formValidation.message.message}
</ValidationMessage>
</Spacer>
<SuccessMessage isSent={formData.isSent}>
Merci, votre message a bien été envoyé !
</SuccessMessage>
<Spacer textAlign="center">
<Button title="Envoyer" type="submit" colors="primary" />
</Spacer>
</FormStyled>
)
}
Below is the request payload when I send the file :
form-name=postuler&job=Tous&firstName=foo&lastName=bar&email=foo.bar%40gmail.com&phoneNumber=0102030405&message=foo%20bar%20baz&cv=%5Bobject%20File%5D&linkedinUrl=https%3A%2F%2Fwww.foobar.fr&isSent=false&validation=%5Bobject%20Object%5D&ignore_whitespace=false&allow_display_name=false&require_display_name=false&allow_utf8_local_part=true&require_tld=true
When I send the form, data are correctly displayed in Netlify form dashboard except the content of the input type file which remains empty. I want the content of the input type file to be displayed in Netlify dashboard (Regarding the doc, I assume it should be a link to access the file).
From what I understand looking carefully at the request payload, I'm sending cv=%5Bobject%20File, so I guess this the problem, because Netlify could not be able to retrieve the real content of the cv input.