Clear Form Fields in React on Submit - javascript

I know this has probably been asked a few times, but I simply cannot figure out how to clear the form fields after submission of the form. It is working perfectly, but all of the data remains in the fields once I submit. I have tried the resetForm but that doesn't seem to be working for me.
Any help is greatly appreciated!
import React from "react";
import axios from "axios";
import '../ticket.min.css'
import Form from 'react-bootstrap/Form'
import Col from 'react-bootstrap/Col'
import Button from 'react-bootstrap/Button'
class Ticket extends React.Component {
state = {
firstName: "",
lastName: "",
email: "",
content: "",
category: "",
urgency: "",
tickets: [],
}
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
handleSubmit = (event) => {
event.preventDefault();
this.setState({
firstName: '',
lastName: '',
email: '',
content: '',
category: '',
urgency: '',
})
};
addTicket = () => {
let url = "http://localhost:8080/tickets";
axios.post(url, {
firstName: this.state.firstName,
lastName: this.state.lastName,
email: this.state.email,
content: this.state.content,
category: this.state.category,
urgency: this.state.selectedOption
}).then(response => {
alert('Your ticket has been submitted');
});
};
getData = () => {
let url = "http://localhost:8080/tickets";
axios
.get(url)
.then((response) => this.setState({ tickets: response.data }));
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>First Name:</label>
<input type="text" name="firstName" value={this.state.firstName} onChange={this.handleChange} />
<br></br>
<label>Last Name:</label>
<input type="text" name="lastName" value={this.state.lastName} onChange={this.handleChange} />
<br></br>
<label>Email:</label>
<input type="text" name="email" value={this.state.email} onChange={this.handleChange} />
<br></br>
<label>
Select a Category:<br></br>
<select value={this.state.category} onChange={(e) => this.setState({ category: e.target.value })}>
<option value="hardware">Hardware</option>
<option value="software">Software</option>
<option value="internet">Internet</option>
<option value="other">Other</option>
</select>
</label>
<label>Please Describe Your Issue:</label>
<br></br>
<textarea value={this.state.content} name="content" onChange={this.handleChange} />
<label>
Select the Urgency Level:<br></br>
<input
type="radio"
name="selectedOption"
value="Urgent"
checked={this.state.selectedOption === "Urgent"}
onChange={this.handleChange}
/>
Urgent<br></br>
<input
type="radio"
name="selectedOption"
value="Normal"
checked={this.state.selectedOption === "Normal"}
onChange={this.handleChange}
/>
Normal<br></br>
<input
type="radio"
name="selectedOption"
value="Low Priority"
checked={this.state.selectedOption === "Low Priority"}
onChange={this.handleChange}
/>
Low Priority
</label>
<button
type="button"
className="btn btn-primary"
onClick={this.addTicket}
>
Submit
</button>
</form>
<h3>Pending Tickets</h3>
<button
type="button"
className="btn btn-primary"
onClick={this.getData}
>
Show Pending
</button>
<ul>
{this.state.tickets.map(p => (
<li key={p.id}>
<b>First Name:</b>{p.firstName} <b>Last Name:</b>{p.lastName} <b>Email:</b>{p.email} <b>Issue:</b>{p.content} <b>Category:</b>{p.category} <b>Urgency:</b>{p.urgency}
</li>
))}
</ul>
</div>
);
}
}
export default Ticket;

Related

Is there a way I can make a react drop down rendered alone

Devs in the house.
I'm working on a little project where a user enters his info and on clicking of an action button, a list is to be dropped down for various options. My issue is that when a button is clicked, all the to-be-dropped-list are equally affected. and I only want the one whose button was clicked to be dropped down.
import React, { useState,useEffect } from 'react'
import Action from './action'
const Form = () => {
document.title = 'Contact Form'
const [action, setAction] = useState(false)
const [people, setPeople] = useState([])
const [user, setUser] = useState({firstName: '', lastName: '', email: '', phone: '',single: '', married: '', student: '', employed: ''})
const handleChange=(e)=>{
const name = e.target.name
const value =e.target.value
setUser({...user, [name]: value})
// console.log(`Name: ${name} Value: ${value}`);
}
var loadFile = function(e){
var image = document.getElementById('output')
image.src = URL.createObjectURL(e.target.files[0])
}
const handleSubmit = (e)=>{
console.log(12345);
e.preventDefault()
if(user.firstName && user.lastName && user.phone){
const newUser = {...user, time: new Date().getTime().toString()}
setPeople([...people, newUser])
// clearing fields
setUser({firstName: '', lastName: '', phone: '', email: ''})
// console.log("People :",people,"User: ",user);
// img
}else{
console.log("Field cannot be empty");
}
}
const showPpt =(e, index, time)=>{
console.log('sibling',e.target.nextElementSibling);
console.log(people);
people.forEach((a,i)=>{
if (a.time === time) {
console.log(e.target.parentElement.parentElement.parentElement);
console.log('old time',a.time, 'btn time',time);
if (action === true) {
setAction(false)
}else if (action === false) {
setAction(true)
}
}
else{
console.log('absent');
console.log('old time',a.time, 'btn time',time);
// setAction(false)
}
})
// if(time === people[index].time){
// console.log('Index ',index,e.target.parentElement.parentElement.parentElement);
// console.log('fetch time',people[index].time, 'current time', time);
// }
}
return (
<section>
<section className="head">
<h1>hello people</h1>
<form>
<section className="inp name">
<label htmlFor="firstName">First Name</label>
<input type="text" name="firstName" placeholder='First name' id="firstName" onChange={handleChange} value={user.firstName} />
<label htmlFor="lastName">Last Name</label>
<input type="text" name="lastName" placeholder='Last name' id="lastName" onChange={handleChange} value={user.lastName}/>
</section>
<section className="inp email">
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email" onChange={handleChange} value={user.email} />
<label htmlFor="phone">Phone</label>
<input type="number" name="phone" id="phone" onChange={handleChange} value={user.phone}/>
</section>
{/* <section className='inp image'>
<label htmlFor="file">Image</label>
<input type="file" accept="image/gif, image/jpeg, image/png" name="image" id="file" style={{display: 'none'}} onChange={loadFile} value={user.fileData}/>
<img id='output' style={{width: '5rem'}} />
</section> */}
<section className="inp Address"></section>
<div className="radio-btn">
<section className="inp mrg-status">
<h4>Relationship</h4>
<div className="cont">
<label htmlFor="single">Single</label>
<input type="radio" name="relationship" id="single" onChange={handleChange} value={"single"}/>
<label htmlFor="married">Married</label>
<input type="radio" name='relationship' id='married' onChange={handleChange} value={"married"}/>
</div>
</section>
<section className="inp employment">
<h4>Employment</h4>
<div className="cont">
<label htmlFor="student">Student</label>
<input type="radio" name="employment" id="student" onChange={handleChange} value={"employed"} />
<label htmlFor="employed">Employed</label>
<input type="radio" name="employment" id="employed" onChange={handleChange} value={"employed"} />
</div>
</section>
</div>
<section className="submit">
<button className='btn' type='submit' onClick={handleSubmit}>Add Person</button>
</section>
</form>
</section>
<section className="main">
{people.map((data, index)=>{
const {firstName, lastName, email, phone, relationship, employment, time} = data
return <article className='user-contact' key={index} {...data}>
<article className="cont">
<div className="info">
<h4>Private information</h4>
<h4>Name: {firstName} {lastName}</h4>
<h4>Phone: {phone}</h4>
<h4>Email: {email}</h4>
<h4>Relationship status: {relationship}</h4>
<h4>Employment status: {employment}</h4>
</div>
<div className="action">
<button className='but' onClick={(e)=>showPpt(e, index, time)}>action</button>
{action && <Action />}
</div>
</article>
</article>
})}
</section>
</section>
)
}
export default Form
That's happen because you deal with an array of people with a single boolean state, which populate all the actions of all people.
I suggest you add an extra field for each element in people array which indicates the active/unactive action.
import React, { useState,useEffect } from 'react'
import Action from './action'
const Form = () => {
document.title = 'Contact Form'
const [action, setAction] = useState(false)
const [people, setPeople] = useState([])
const [user, setUser] = useState({firstName: '', lastName: '', email: '', phone: '',single: '', married: '', student: '', employed: ''})
const handleChange=(e)=>{
const name = e.target.name
const value =e.target.value
setUser({...user, [name]: value})
// console.log(`Name: ${name} Value: ${value}`);
}
var loadFile = function(e){
var image = document.getElementById('output')
image.src = URL.createObjectURL(e.target.files[0])
}
const handleSubmit = (e)=>{
console.log(12345);
e.preventDefault()
if(user.firstName && user.lastName && user.phone){
const newUser = {...user, time: new Date().getTime().toString(), active: false}
setPeople([...people, newUser])
// clearing fields
setUser({firstName: '', lastName: '', phone: '', email: ''})
// console.log("People :",people,"User: ",user);
// img
}else{
console.log("Field cannot be empty");
}
}
const showPpt =(e, index, time)=>{
let personIndex = people.findIndex(a => a.time === time);
setPeople((prev) => {
prev[personIndex].active = !prev[personIndex].active
return [...prev]
})
}
return (
<section>
<section className="head">
<h1>hello people</h1>
<form>
<section className="inp name">
<label htmlFor="firstName">First Name</label>
<input type="text" name="firstName" placeholder='First name' id="firstName" onChange={handleChange} value={user.firstName} />
<label htmlFor="lastName">Last Name</label>
<input type="text" name="lastName" placeholder='Last name' id="lastName" onChange={handleChange} value={user.lastName}/>
</section>
<section className="inp email">
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email" onChange={handleChange} value={user.email} />
<label htmlFor="phone">Phone</label>
<input type="number" name="phone" id="phone" onChange={handleChange} value={user.phone}/>
</section>
{/* <section className='inp image'>
<label htmlFor="file">Image</label>
<input type="file" accept="image/gif, image/jpeg, image/png" name="image" id="file" style={{display: 'none'}} onChange={loadFile} value={user.fileData}/>
<img id='output' style={{width: '5rem'}} />
</section> */}
<section className="inp Address"></section>
<div className="radio-btn">
<section className="inp mrg-status">
<h4>Relationship</h4>
<div className="cont">
<label htmlFor="single">Single</label>
<input type="radio" name="relationship" id="single" onChange={handleChange} value={"single"}/>
<label htmlFor="married">Married</label>
<input type="radio" name='relationship' id='married' onChange={handleChange} value={"married"}/>
</div>
</section>
<section className="inp employment">
<h4>Employment</h4>
<div className="cont">
<label htmlFor="student">Student</label>
<input type="radio" name="employment" id="student" onChange={handleChange} value={"employed"} />
<label htmlFor="employed">Employed</label>
<input type="radio" name="employment" id="employed" onChange={handleChange} value={"employed"} />
</div>
</section>
</div>
<section className="submit">
<button className='btn' type='submit' onClick={handleSubmit}>Add Person</button>
</section>
</form>
</section>
<section className="main">
{people.map((data, index)=>{
const {firstName, lastName, email, phone, relationship, employment, time} = data
return <article className='user-contact' key={index} {...data}>
<article className="cont">
<div className="info">
<h4>Private information</h4>
<h4>Name: {firstName} {lastName}</h4>
<h4>Phone: {phone}</h4>
<h4>Email: {email}</h4>
<h4>Relationship status: {relationship}</h4>
<h4>Employment status: {employment}</h4>
</div>
<div className="action">
<button className='but' onClick={(e)=>showPpt(e, index, time)}>action</button>
{action && <Action />}
</div>
</article>
</article>
})}
</section>
</section>
)
}
export default Form

Checkbox value return undefined

Hello guys i have a problem, i have a 2 checkbox, each of them have value. The first checkbox is Any/Not, and the second one is Valid/Invalid. If the checkbox is checked the value will change to Any, if not checked the value will be not, same for the valid/invalid one.
I already tried, but when the checkbox is unchecked the value im getting is undefined. Btw i use react, node, and mysql. But the value is succesfully changed when the box is checked.
Here is the code :
FormDataProvider.js
import React from 'react';
import {createContext, useState} from "react"
export const FormData = createContext();
export default function FormDataProvider({children}) {
const [formData , setFormData] = useState({
cName : "",
Address : "",
phoneNumber : "",
presidentName : "",
managerEmail : "",
managerPhone : "",
picEmail : "",
picPhone : "",
date: "",
mainBusiness : "",
employeeNumber : "",
numberOfCustomer : "",
myFile : "",
any : "" ,
valid : ""
});
return (
<FormData.Provider value={{ formData, setFormData }}>
{children}
</FormData.Provider>
);
}
Form.js
const Form = () => {
let navigate = useNavigate();
Axios.defaults.withCredentials = true;
const { emailLog, setEmailLog } = useContext(EmailUser);
const { loginStatus, setLoginStatus } = useContext(LoginStatus);
const { formData , setFormData} = useContext(FormData);
const handleChange = event => {
if (event.target.checked) {
setFormData({...formData, any : event.target.checked})
} else {
setFormData({...formData, any : "Not"})
}
};
const handleChange2 = event => {
if (event.target.checked) {
setFormData({...formData, valid : event.target.checked})
} else {
setFormData({...formData, valid : "Invalid"})
}
};
return (
<form method='POST' encType='multipart/form-data' action='http://localhost:3001/registration'>
<div className=''>
<input className='inputForm' type='email' value={emailLog} name='email' required onChange={(e) => {
setEmailLog(e.target.value) }} />
<input className='inputForm' type='text' placeholder='Company Name' name="CompanyName" required value={formData.cName} onChange={(event) =>
setFormData({ ...formData, cName: event.target.value })}/>
<input className='inputForm' type='text' placeholder='Address' name="Address" required value={formData.Address} onChange={(event) =>
setFormData({ ...formData, Address: event.target.value })} />
<input className='inputForm' type='tel' placeholder='Phone Number' name="Phone" required value={formData.phoneNumber} onChange={(event) =>
setFormData({ ...formData, phoneNumber: event.target.value })} />
<input className='inputForm' type='text' placeholder='President Director Name' name="PresidentName" required value={formData.presidentName} onChange={(event) =>
setFormData({...formData, presidentName: event.target.value})} />
<input className='inputForm' type='email' placeholder='Manager Email' name="ManagerEmail" required value={formData.managerEmail} onChange={(event) =>
setFormData({...formData, managerEmail: event.target.value})} />
<input className='inputForm' type='tel' placeholder='Manager Phone' name="ManagerPhone" required value={formData.managerPhone} onChange={(event) =>
setFormData({...formData, managerPhone: event.target.value})} />
<input className='inputForm' type='email' placeholder='PIC Email' name="PICEmail" required value={formData.picEmail} onChange={(event) =>
setFormData({...formData, picEmail: event.target.value})} />
<input className='inputForm' type='tel' placeholder='PIC Phone' name="PICPhone" required value={formData.picPhone} onChange={(event) =>
setFormData({...formData, picPhone: event.target.value})} />
<input className='inputForm' type='date' placeholder='Date' name="EstablishedDate" required value={formData.date} onChange={(event) =>
setFormData({...formData, date: event.target.value})} />
<select className='selectBox' name='ChoiceBusiness' required onChange={(event) =>
setFormData({...formData, mainBusiness: event.target.value})} >
<option value="" disabled selected hidden>Choose Main Business...</option>
<option value="Software License">Software License</option>
<option value="IT Services & Consulting">IT Services & Consulting</option>
<option value="IT Outsourcing">IT Outsourcing</option>
<option value="Hardware">Hardware</option>
<option value="General Trading">General Trading</option>
<option value="Others">Others</option>
</select>
<select className='selectBox' name='EmployeeNumber' required onChange={(event) =>
setFormData({...formData, employeeNumber: event.target.value})} >
<option value="" disabled selected hidden>Choose Employee Number...</option>
<option value="1-50">1-50</option>
<option value="51-100">51-100</option>
<option value="101-250">101-250</option>
<option value="251-500">251-500</option>
<option value="500+">500+</option>
</select>
<input className='inputForm' type="number" placeholder='Number of Customer' name="NumberOfCustomer" required value={formData.numberOfCustomer} onChange={(event) =>
setFormData({...formData, numberOfCustomer: event.target.value})} />
<input className='inputFormDate' type="file" name='pdfFiles' multiple required onChange={(event) =>
setFormData({...formData, myFile : event.target.value})} />
<div className='formCheckboxes'>
<div className='formCheckbox'>
<p>SK Menhum & Akta Notaris</p>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" value="Any" name="Any" onChange={handleChange}/>
<label class="form-check-label" for="inlineCheckbox1">Any</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" value="Valid" name="Valid" onChange={handleChange2}/>
<label class="form-check-label" for="inlineCheckbox2">Valid</label>
</div>
</div>
</div>
<button className='btnSubmit' type='submit'> Submit</button>
</div>
</form>
)
}
export default Form
Always use the functional update format to update state based on its previous value to prevent loss of batched state updates.
When checked, you're setting the value to the checked property which is a Boolean. You want the value property instead
Try something like this
setFormData((fd) => ({
...fd,
any: event.target.checked ? event.target.value : "Not",
}));
You could probably use something generic for all inputs provided their name attributes match the object keys you want.
Checkboxes could provide their off value in a data-attribute, eg
<input
class="form-check-input"
type="checkbox"
value="Any"
data-off="None"
name="any"
onChange={handleChange}
/>
// generic handler for all inputs
const handleChange = (e) => {
let value;
switch (e.target.type) {
case "checkbox":
value = e.target.checked ? e.target.value : e.target.dataset.off;
break;
case "file":
value = e.target.files[0];
break;
default:
value = e.target.value;
}
setFormData((fd) => ({
...fd,
[e.target.name]: value,
}));
};

React Form values are not reflected on the FORM items for EDIT using class state

I'm pulling data from MongoDB and trying to edit the data but for some reason, my form is not showing the values on the form. Can anyone help to guide me on what I am getting wrong? below is my code for any help why form value are not updated using this.state.job_title as an example:
edit-job.component.js
import React, { Component } from "react";
import axios from "axios";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
export default class EditJob extends Component {
constructor(props) {
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangeJob_title = this.onChangeJob_title.bind(this);
this.onChangejob_comp_image = this.onChangejob_comp_image.bind(this);
this.onChangejob_comp_name = this.onChangejob_comp_name.bind(this);
this.onChangejob_description = this.onChangejob_description.bind(this);
this.onChangejob_location = this.onChangejob_location.bind(this);
this.onChangejob_field = this.onChangejob_field.bind(this);
this.onChangeDatejob_closing_date =
this.onChangeDatejob_closing_date.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username: "",
job_title: "",
job_comp_image: "",
job_comp_name: "",
job_description: "",
job_location: "",
job_field: "",
job_closing_date: new Date(),
users: [],
};
}
componentDidMount() {
//GET CURRENT JOB LISTING TO EDIT
if (this.props.match && this.props.match.params.id) {
axios
.get("http://localhost:5001/jobs/" + this.props.match.params.id)
.then((response) => {
console.log(response.data);
this.setState({
username: response.data.username,
job_title: response.data.job_title,
job_comp_image: response.data.job_comp_image,
job_comp_name: response.data.job_comp_name,
job_description: response.data.job_description,
job_location: response.data.job_location,
job_field: response.data.job_field,
job_closing_date: new Date(response.data.job_closing_date),
});
})
.catch(function (error) {
console.log(error);
});
}
axios
.get("http://localhost:5001/users/")
.then((response) => {
if (response.data.length > 0) {
this.setState({
users: response.data.map((user) => user.username),
});
}
})
.catch((error) => {
console.log(error);
});
}
onChangeUsername(e) {
this.setState({
username: e.target.value,
});
}
//Update user with new username entered by user
onChangeJob_title(e) {
this.setState({
job_title: e.target.value,
});
}
onChangejob_comp_image(e) {
this.setState({
job_comp_image: e.target.value,
});
}
onChangejob_comp_name(e) {
this.setState({
job_comp_name: e.target.value,
});
}
onChangejob_description(e) {
this.setState({
job_description: e.target.value,
});
}
onChangejob_location(e) {
this.setState({
job_location: e.target.value,
});
}
onChangejob_field(e) {
this.setState({
job_field: e.target.value,
});
}
onChangeDatejob_closing_date(job_closing_date) {
this.setState({
job_closing_date: job_closing_date,
});
}
onSubmit(e) {
e.preventDefault();
const job = {
username: this.state.username,
job_title: this.state.username,
job_comp_image: this.state.job_comp_image,
job_comp_name: this.state.job_comp_name,
job_description: this.state.job_description,
job_location: this.state.job_location,
job_field: this.state.job_field,
job_closing_date: new Date(),
};
console.log(job);
axios
.post(
"http://localhost:5001/jobs/update/" + this.props.match.params.id,
job
)
.then((res) => console.log(res.data));
window.location = "/";
}
render() {
const Headerstyle = {
marginTop: "40px",
};
return (
<div style={Headerstyle}>
<h3>Edit Exercise Log</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select
UseRef="userInput"
required
className="form-control"
value={this.state.username}
onChange={this.onChangeUsername}
>
{this.state.users.map(function (user) {
return (
<option key={user} value={user}>
{user}
</option>
);
})}
</select>
</div>
<div className="form-group">
<label>Job Title: </label>
<input
type="text"
required
className="form-control"
value={this.state.job_title}
onChange={this.onChangeJob_title}
/>
</div>
<div className="form-group">
<label>Company Image: </label>
<input
type="text"
className="form-control"
value={this.state.job_comp_image}
onChange={this.onChangejob_comp_image}
/>
</div>
<div className="form-group">
<label>Company Name: </label>
<input
type="text"
className="form-control"
value={this.state.job_comp_name}
onChange={this.onChangejob_comp_name}
/>
</div>
<div className="form-group">
<label>Job Description: </label>
<input
type="text"
className="form-control"
value={this.state.job_description}
onChange={this.onChangejob_description}
/>
</div>
<div className="form-group">
<label>Job Location: </label>
<input
type="text"
className="form-control"
value={this.state.job_location}
onChange={this.onChangejob_location}
/>
</div>
<div className="form-group">
<label>Job related field: </label>
<input
type="text"
className="form-control"
value={this.state.job_field}
onChange={this.onChangejob_field}
/>
</div>
<div className="form-group">
<label>Job Closing Date: </label>
<div>
<DatePicker
selected={this.state.job_closing_date}
onChange={this.onChangeDatejob_closing_date}
/>
</div>
</div>
<div className="form-group">
<input
type="submit"
value="Edit Job Listing"
className="btn btn-primary"
/>
</div>
</form>
</div>
);
}
}

Get selected value dropdown React useSate

Originally, I designed this component to have a useState for each individual input. After realizing that this would not be the best approach for adding new inputs, I refactored to use only one useState. I'm able to get the values for all, but gender. I'm hoping someone could point me in the right direction.
Note: I realize it's not picking up the value because I'm not using person.gender. I went ahead and tried to add value={person.gender = "the value I want"} for each input.
const Forms = () => {
const [person, setPerson] = useState({
firstName: "",
lastName: "",
age: "",
gender: "",
email: "",
});
const [people, setPeople] = useState([]);
const handleChange = (e) => {
const name = e.target.name;
const value = e.target.value;
setPerson({ ...person, [name]: value });
};
const handleSubmit = (e) => {
e.preventDefault();
if (person.firstName && person.lastName && person.age && person.email) {
const newPerson = {
...person,
id: new Date().getTime().toString(),
};
setPeople([...people, newPerson]);
setPerson({
firstName: "",
lastName: "",
age: "",
gender: "",
email: "",
});
}
};
console.log(person.gender);
return (
<article>
<h2>Forms</h2>
<form className="form">
<div className="form-control">
<label htmlFor="firstName">First Name:</label>
<input
type="text"
id="firstName"
name="firstName"
value={person.firstName}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label htmlFor="lastName">Last Name:</label>
<input
type="text"
id="LastName"
name="lastName"
value={person.lastName}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label htmlFor="age">Age:</label>
<input
type="text"
id="age"
name="age"
value={person.age}
onChange={handleChange}
/>
</div>
<div className="form-control">
<label htmlFor="gender">Gender:</label>
<select onChange={handleChange} id="gender">
<option name="gender" value="male">
Male
</option>
<option name="gender" value="female">
Female
</option>
<option name="gender" value="prefer not to answer">
prefer not to answer
</option>
</select>
</div>
<div className="form-control">
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
value={person.email}
onChange={handleChange}
/>
</div>
<button type="submit" className="btn" onClick={handleSubmit}>
Submit
</button>
</form>
{people.map((person) => {
const { firstName, lastName, age, gender, email, id } = person;
return (
<div className="item" key={id}>
<h4>
{firstName} {lastName}
</h4>
<span>{age}</span>
<span>{gender}</span>
<p>{email}</p>
</div>
);
})}
</article>
);
};
export default Forms;
Thanks,
Sean
You have to give the name attribute to the select element, not to its options
<select name="gender" onChange={handleChange} id="gender">
Try reading documentation in react about forms
https://reactjs.org/docs/forms.html
Another thing I think it e.target.value is not working in select form, also you shoud use independent state for every form input because in this layer you cause some effect and rerender

Unable to get form data after setState

I am trying to send form data after submitting to the firebase database using redux in my react application, but I am unable to send the state so I tried tracking form data by console.log but the form data is empty. I am able to console log params but not this.state
Below is the code.
I am using redux in this app. createUser is my action
import React, { Component } from "react";
import { connect } from "react-redux";
import { createUser } from "../store/actions/userActions";
class UserForm extends Component {
constructor(props) {
super(props);
this.state = { form: [], alert: false, alertData: {} };
this.submitMessage = this.submitMessage.bind(this);
}
submitMessage = e => {
e.preventDefault();
const params = {
name: this.inputName.value,
email: this.inputEmail.value,
city: this.inputCity.value,
age: this.inputAge.value
};
this.setState({ form: params });
console.log(params);
console.log("-----------");
console.log(this.state);
this.props.createUser(this.state);
};
render() {
return (
<div className="container">
<div
className="row"
>
User
</div>
<div className="container" style={{ padding: `10px 0px` }} />
<div className="row">
<div className="col-sm-4">
<h2>Contact Form</h2>
<form onSubmit={this.submitMessage} ref="contactForm">
<div className="form-group">
<label htmlFor="name">Name</label>
<input
type="text"
className="form-control"
id="name"
placeholder="Name"
ref={name => (this.inputName = name)}
/>
</div>
<div className="form-group">
<label htmlFor="emai1">Email</label>
<input
type="email"
className="form-control"
id="email"
placeholder="Email"
ref={email => (this.inputEmail = email)}
/>
</div>
<div className="form-group">
<label htmlFor="city">City</label>
<select
className="form-control"
id="city"
ref={city => (this.inputCity = city)}
>
<option value="India">India</option>
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="Japan">Japan</option>
<option value="Germany">Germany</option>
</select>
</div>
<div className="form-group">
<label htmlFor="age">Age</label>
<input
type="number"
className="form-control"
id="age"
placeholder="Age"
ref={age => (this.inputAge = age)}
/>
</div>
<button type="submit" className="btn btn-primary">
Send
</button>
</form>
</div>
</div>
</div>
);
}
}
const mapStateToProps = state => {
return {};
};
const mapDispatchToProps = dispatch => {
return {
createUser: user => dispatch(createUser)
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(UserForm);
Due to setState is asynchronous you can access the changed state in a callback which you can pass as a second param to setState method. Please read more about setState
submitMessage = e => {
e.preventDefault();
const params = {
name: this.inputName.value,
email: this.inputEmail.value,
city: this.inputCity.value,
age: this.inputAge.value
};
this.setState({ form: params }, () => {
console.log(params);
console.log("-----------");
console.log(this.state);
this.props.createUser(this.state);
});
};
You call createUser before setState is finished. Why use the state anyway? I would suggest:
submitMessage = e => {
e.preventDefault();
const params = {
name: this.inputName.value,
email: this.inputEmail.value,
city: this.inputCity.value,
age: this.inputAge.value
};
this.props.createUser(params);
};
There is you are missing two things,
Set state is async in nature so after set state, you must use call back to access it.
You are not passing form data ie. Params to createUser
Solution :
import React, { Component } from "react";
import { connect } from "react-redux";
import { createUser } from "../store/actions/userActions";
class UserForm extends Component {
constructor(props) {
super(props);
this.state = { form: [], alert: false, alertData: {} };
this.submitMessage = this.submitMessage.bind(this);
}
submitMessage = e => {
e.preventDefault();
const params = {
name: this.inputName.value,
email: this.inputEmail.value,
city: this.inputCity.value,
age: this.inputAge.value
};
this.setState({ form: params },()=>{
this.props.createUser(this.state);
});
};
render() {
return (
<div className="container">
<div
className="row"
>
User
</div>
<div className="container" style={{ padding: `10px 0px` }} />
<div className="row">
<div className="col-sm-4">
<h2>Contact Form</h2>
<form onSubmit={this.submitMessage} ref="contactForm">
<div className="form-group">
<label htmlFor="name">Name</label>
<input
type="text"
className="form-control"
id="name"
placeholder="Name"
ref={name => (this.inputName = name)}
/>
</div>
<div className="form-group">
<label htmlFor="emai1">Email</label>
<input
type="email"
className="form-control"
id="email"
placeholder="Email"
ref={email => (this.inputEmail = email)}
/>
</div>
<div className="form-group">
<label htmlFor="city">City</label>
<select
className="form-control"
id="city"
ref={city => (this.inputCity = city)}
>
<option value="India">India</option>
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="Japan">Japan</option>
<option value="Germany">Germany</option>
</select>
</div>
<div className="form-group">
<label htmlFor="age">Age</label>
<input
type="number"
className="form-control"
id="age"
placeholder="Age"
ref={age => (this.inputAge = age)}
/>
</div>
<button type="submit" className="btn btn-primary">
Send
</button>
</form>
</div>
</div>
</div>
);
}
}
const mapStateToProps = state => {
return {};
};
const mapDispatchToProps = dispatch => {
return {
createUser: user => dispatch(createUser(user))
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(UserForm);

Categories

Resources