I would like to do a form with select. I use hooks and I use react-select for this.
My problems: The field select doesn't show the default value. When I select value the field don't show it. When I click on submit button, no value are send.
I don't understand why, could someone help me please?
This is my code:
import React, { useState } from "react";
import emailjs from "emailjs-com";
import styles from "../../styles/ContactForm.module.scss";
import Select from 'react-select'
function Field({ name, value, onChange, children }) {
return (
<div className="form-group mb-2">
<label htmlFor={name}>{children}</label>
<input
type="text"
value={value}
onChange={onChange}
id={name}
name={name}
className="form-control"
/>
</div>
);
}
function FieldRequired({ name, value, onChange, children }) {
return (
<div className="form-group mb-2">
<label htmlFor={name}>{children}</label>
<input
type="text"
value={value}
onChange={onChange}
required
id={name}
name={name}
className="form-control"
/>
</div>
);
}
function FieldTel({ name, value, onChange, children }) {
return (
<div className="form-group mb-2">
<label htmlFor={name}>{children}</label>
<input
type="tel"
pattern="^(?:(?:\ |00)33[\s.-]{0,3}(?:\(0\)[\s.-]{0,3})?|0)[1-9](?:(?:[\s.-]?\d{2}){4}|\d{2}(?:[\s.-]?\d{3}){2})$"
value={value}
onChange={onChange}
id={name}
name={name}
className="form-control"
/>
<small className="form-text text-muted">
Votre téléphone servira uniquement a vous contacter pour votre demande.
</small>
</div>
);
}
function CheckBox({ name, value, onChange, children }) {
return (
<div className="form-check mb-2">
<input
type="checkbox"
checked={value}
onChange={onChange}
id={name}
name={name}
required
className="form-check-input"
/>
<label htmlFor={name} className="form-check-label">
{children}
</label>
</div>
);
}
function EmailBox({ name, value, onChange, children }) {
return (
<div className="form-group mb-2">
<label htmlFor={name}>{children}</label>
<input
type="email"
pattern="^[a-zA-Z0-9.!#$%&'* /=?^_`{|}~-] @[a-zA-Z0-9-] (?:\.[a-zA-Z0-9-] )*$"
value={value}
onChange={onChange}
required
id={name}
name={name}
className="form-control"
/>
<small className="form-text text-muted">
Votre email servira uniquement a vous contacter pour votre demande.
</small>
</div>
);
}
function TextArea({ name, value, onChange, children }) {
return (
<div className="form-group mb-2">
<label htmlFor={name}>{children}</label>
<textarea
rows="3"
maxLength="2000"
value={value}
onChange={onChange}
id={name}
name={name}
className="form-control"
/>
</div>
);
}
let options = [
{value: "vitrine-cms", label: "Site vitrine CMS"},
{value: "vitrine-main", label: "Site vitrine sur-mesure"},
{value: "eCommerce", label: "Site eCommerce"},
{value: "autre-site", label: "Autre site"},
{value: "ponctuel", label: "Mission ponctuelle"},
{value: "maintenance", label: "Maintenance"},
{value: "autre", label: "Autre choix"},
]
function SelectFieldRequired(name, value, onChange) {
return(
<>
<div>Nature de la demande</div>
<Select
name={name}
value={value}
defaultValue={options[1]}
onChange={onChange}
options={options}
/>
</>
)
}
export default function ContactForm() {
const [form, setForm] = useState({
lastName: "",
to_name: "service_.....",
firstName: "",
company: "",
phone: "",
email: "",
natureOfTheRequest: options[1],
message: "",
acceptCGU: false,
});
const sendEmail = (e) => {
e.preventDefault();
emailjs
.sendForm(
"service_....",
"template_.....",
e.target,
"user_......"
)
.then(
(result) => {
console.log(result);
alert("Email bien envoyé!!!");
},
(error) => {
console.log(error);
}
);
e.target.reset();
};
const onChange = (value) => {
setForm((prevForm) => ({
...prevForm,
natureOfTheRequest: value
}));
};
return (
<div className="container">
<form onSubmit={sendEmail}>
{/* ............................................................................................ */}
<FieldRequired name="lastName" value={form.lastName} onChange={setForm}>
Nom *
</FieldRequired>
{/* ............................................................................................ */}
<Field name="firstName" value={form.firstName} onChange={setForm}>
Prénom
</Field>
{/* ............................................................................................ */}
<Field name="company" value={form.company} onChange={setForm}>
Société
</Field>
{/* ............................................................................................ */}
<FieldTel name="phone" value={form.phone} onChange={setForm}>
Téléphone
</FieldTel>
{/* ............................................................................................ */}
<EmailBox name="email" value={form.email} onChange={setForm}>
Email *
</EmailBox>
{/* ............................................................................................ */}
<SelectFieldRequired
className="request col-12"
name="natureOfTheRequest"
value={form.natureOfTheRequest}
onChange={onChange}
id="natureOfTheRequest"
/>
{/* <div className="form-group mb-2">
<label className="request col-12" htmlFor="request">
Nature de la demande *
</label>
<select
id="natureOfTheRequest"
name="natureOfTheRequest"
onChange={setForm}
value={form.natureOfTheRequest}
required
className="py-1 rounded-3"
>
<option value="">Sélectionnez</option>
<option value="vitrine-cms">Site vitrine Wordpress</option>
<option value="vitrine-main">Site vitrine sur-mesure</option>
<option value="eCommerce">Site E-Commerce CMS</option>
<option value="autre-site">Autre site sur-mesure</option>
<option value="ponctuel">Travail ponctuel</option>
<option value="maintenance">Maintenance</option>
<option value="autre">Autre sujet</option>
</select>
</div>
*/} {/* ............................................................................................ */}
<TextArea name="message" value={form.message} onChange={setForm}>
Explication sur votre demande
</TextArea>
{/* ............................................................................................ */}
{/* ............................................................................................ */}
<CheckBox name="acceptCGU" value={form.acceptCGU} onChange={setForm}>
J'accepte que mes données soient utilisées pour me contacter *
</CheckBox>
{/* ............................................................................................ */}
{/* SUBMIT button */}
<button
type="submit"
id={styles.submitButton}
className="btn btn-primary"
>
{" "}
Envoyer le formulaire
</button>
</form>
</div>
);
}
CodePudding user response:
You're setting the Select
value to form.natureOfTheRequest
, so you need to update that specific field on its onChange
callback, rather than simply passing setForm
.
The callback could look like the following.
const onChange = (value) => {
setForm((prevForm) => ({
...prevForm,
natureOfTheRequest: value
}));
};
Then, modify the SelectFieldRequired
's onChange
prop to receive it.
<SelectFieldRequired
className="request col-12"
name="natureOfTheRequest"
value={form.natureOfTheRequest}
onChange={onChange}
id="natureOfTheRequest"
/>
Since you're explicitly setting the value on the Select
, that also overrides the defaultValue
you have set. Instead, you can set the form.natureOfTheRequest
initial value to options[1]
.
const [form, setForm] = useState({
lastName: "",
to_name: "service_........",
firstName: "",
company: "",
phone: "",
email: "",
natureOfTheRequest: options[1],
message: "",
acceptCGU: false,
});
You also need to change the SelectFieldRequired
component signature, as the props have to be destructured from the props
object.
function SelectFieldRequired({ name, value, onChange }) {
//...
}
Full code example:
let options = [
{value: "vitrine-cms", label: "Site vitrine CMS"},
{value: "vitrine-main", label: "Site vitrine sur-mesure"},
{value: "eCommerce", label: "Site eCommerce"},
{value: "autre-site", label: "Autre site"},
{value: "ponctuel", label: "Mission ponctuelle"},
{value: "maintenance", label: "Maintenance"},
{value: "autre", label: "Autre choix"},
]
// Change props to an object with fields here
function SelectFieldRequired({ name, value, onChange }) {
return(
<>
<div>Nature de la demande *</div>
<Select
name={name}
value={value}
defaultValue={options[1]}
onChange={onChange}
required
options={options}
/>
</>
)
}
export default function ContactForm() {
const [form, setForm] = useState({
lastName: "",
to_name: "service_........",
firstName: "",
company: "",
phone: "",
email: "",
natureOfTheRequest: options[1],
message: "",
acceptCGU: false,
});
const sendEmail = (e) => {
// Omitted for simplicity
};
const onChange = (value) => {
setForm((prevForm) => ({
...prevForm,
natureOfTheRequest: value
}));
};
return (
<div className="container">
<form onSubmit={sendEmail}>
<SelectFieldRequired
className="request col-12"
name="natureOfTheRequest"
value={form.natureOfTheRequest}
onChange={onChange}
id="natureOfTheRequest"
/>
{/* SUBMIT button */}
<button
type="submit"
id={styles.submitButton}
className="btn btn-primary"
>
{" "}
Envoyer le formulaire
</button>
</form>
</div>
);
}
Minimal working example in Codesandbox: https://codesandbox.io/s/bold-oskar-d1in0