I want to clear the input field after upload and submit the form.
I have checked couple of documentation, where its said after submitting the form I can return the initial state.
Here is my code
state = {
firstname: "",
lastname: "",
email: "",
file: null
};
onDrop = e => {
this.setState({ file: e.target.files[0] });
console.log({ file: e.target.files[0] });
};
handleChange = e => {
this.setState({ [e.target.id]: e.target.value });
};
handleSubmit = async e => {
e.preventDefault();
console.log(this.state);
const formData = new FormData();
formData.append("file", this.state.file);
formData.append("upload_preset", process.env.REACT_APP_UPLOAD_PRESET);
const response = await axios.post(
`https://api.cloudinary.com/v1_1/${process.env.REACT_APP_CLOUD_NAME}/image/upload`,
formData
);
await this.props.addPerson({
variables: {
firstname: this.state.firstname,
lastname: this.state.lastname,
email: this.state.email,
image: response.data.url
},
refetchQueries: [{ query: getperson }]
});
this.setState({ firstname: " ", lastname: "", email: " ", file: null }); **this is where i retutn the initial state after submitting the form, but it did not work**
};
This is my form setup
<React.Fragment>
<div>
<form id="addPerson" onSubmit={this.handleSubmit}>
<div className="field">
<label> Firstname </label>
<input type="text" id="firstname" onChange={this.handleChange} />
</div>
<div className="field">
<label> Lastname </label>
<input type="text" id="lastname" onChange={this.handleChange} />
</div>
<div className="field">
<label> Email </label>
<input type="email" id="email" onChange={this.handleChange} />
</div>
<input type="file" onChange={this.onDrop} />
<button>Add Person</button>
</form>
</div>
</React.Fragment>
It doesn't work because your inputs are not fully controlled by react, If you want to control these inputs, you need to specify the value attribute like this :
<input type="text" id="firstname" value={this.state.firstname} onChange={this.handleChange}/>
<input type="text" id="lastname" value={this.state.lastname} onChange={this.handleChange}/>
Note that the file input is always uncontrolled in react (see the documentation), so you need to reset it manually by using a reference :
constructor() {
this.fileRef = React.createRef();
...
}
handleSubmit = async e => {
// Reset the file input
this.fileRef.current.value = '';
};
render() {
...
<input type="file" ref={this.fileRef} onChange={this.onDrop} />
...
}
You haven't set the value attribute in html input with state value.
Since the value attribute is set on our form element, the displayed value will always be this.state.value, making the React state the source of truth.
Since handleChange runs on every keystroke to update the React state, the displayed value will update as the user types.
With a controlled component, every state mutation will have an associated handler function. This makes it straightforward to modify or validate user input.
For more details please check here.
Use following code,
<React.Fragment>
<div>
<form id="addPerson" onSubmit={this.handleSubmit}>
<div className="field">
<label> Firstname </label>
<input type="text" id="firstname" value={this.state.firstname} onChange={this.handleChange} />
</div>
<div className="field">
<label> Lastname </label>
<input type="text" id="lastname" value={this.state.lastname} onChange={this.handleChange} />
</div>
<div className="field">
<label> Email </label>
<input type="email" id="email" value={this.state.email} onChange={this.handleChange} />
</div>
<input type="file" onChange={this.onDrop} />
<button>Add Person</button>
</form>
</div>
</React.Fragment>
Hope this will help you !!!
Related
I have an Form Data input in react js application. I have tried below code to set Form Data state variable but value is showing as empty. Please check below code and advise how to do this...
Initial State :-
this.state = {
FormData: [{
UserId: 0,
FirstName: '',
LastName: '',
EmailId: '',
MobileNo: '',
DivisionId:'',
UserName: '',
Password: '',
ConfirmPassword: '',
RoleId: '',
UpdateUserName: localStorage.getItem("UserId"),
GridState: []
}],
};
Setting State Value in onchange event :-
onChangeHandler = (event) => {
let nam = event.target.name;
let val = event.target.value;
this.setState({[nam]: val});
}
HTML render:-
render() {
<div className="form-group row">
<label className="col-sm-1 col-form-label col-form-label-sm">First Name</label>
<div className="col-sm-3">
<input type="text" name="FormData.FirstName" className="form-control form-control-sm" id="TxtFirstName" placeholder="First Name" required onChange={this.onChangeHandler}/>
</div>
<label className="col-sm-1 col-form-label col-form-label-sm">Last Name</label>
<div className="col-sm-3">
<input type="text" name="FormData.LastName" className="form-control form-control-sm" id="TxtLastName" placeholder="Last Name" required onChange={this.onChangeHandler}/>
</div>
<label className="col-sm-1 col-form-label col-form-label-sm">Email Id</label>
<div className="col-sm-3">
<input type="email" name ="FormData.EmailId" className="form-control form-control-sm" id="TxtEmailId" placeholder="EmailId" required onChange={this.onChangeHandler}/>
</div>
</div>
<div className="form-group row">
<label className="col-sm-1 col-form-label col-form-label-sm">Mobile No</label>
<div className="col-sm-3">
<input type="text" name ="FormData.MobileNo" className="form-control form-control-sm" id="TxtMobileNo" placeholder="Mobile No" onChange={this.onChangeHandler} />
</div>
<label className="col-sm-1 col-form-label col-form-label-sm">User Name</label>
<div className="col-sm-3">
<input type="text" name ="FormData.UserName" className="form-control form-control-sm" id="TxtUserName" placeholder="User Name" required onChange={this.onChangeHandler}/>
</div>
</div>
<div className="form-group row">
<label className="col-sm-1 col-form-label col-form-label-sm">Password</label>
<div className="col-sm-3">
<input type="password" name ="FormData.Password" className="form-control form-control-sm" id="TxtPassword" placeholder="Password" required onChange={this.onChangeHandler}/>
</div>
Please check submit button handling code :-
onSubmitHandler = (event) => {
event.preventDefault();
console.log(JSON.stringify(this.state.FormData));
alert(JSON.stringify(this.state.FormData));
}
Flatten your state structure to be just the form fields
this.state = {
userId : 0,
firstName: '',
lastName : '',
emailId : '',
mobileNo : '',
divisionId :'',
userName : '',
password : '',
confirmPassword : '',
roleId : '',
updateUserName : localStorage.getItem("UserId"),
gridState : []
};
Leave onChangeHandler as-is since it handles a flat state structure already.
Update onSubmitHandler to stringify the state object representing the form fields
onSubmitHandler = (event) => {
event.preventDefault();
console.log(JSON.stringify(this.state));
alert(JSON.stringify(this.state));
}
Update form field names to match that in state. Example:
<input
type="text"
name="firstName" // <-- should match key in state
className="form-control form-control-sm"
id="TxtFirstName"
placeholder="First Name"
required
onChange={this.onChangeHandler}
/>
Note: camelCased all keys/names by normal naming convention.
The value of name in component's state and in HTML are not the same -:
In HTML it is -:
FormData.UserId
similarly for all other fields....
In JS it is only -:
UserId
similarly for all other fields....
FormData prefix is not there in state
you can do something like this -:
onChangeHandler = ({target: {name, value} }) => {
name = name.split(".")[1];
const FormData = {...this.state.FormData, [name]: value};
this.setState(FormData);
}
I am new to react and when I change my state from just variables to an object the input box no longer works.
The following code works
class AddMovie extends Component {
state = {
title: "",
watched: ""
}
onChangeMovie = (e) => {
this.setState({[e.target.name] : e.target.value});
}
uploadMovie = (e) => {
e.preventDefault();
this.props.addMovie(this.state.title, this.state.watched);
this.setState({title: "", watched: ""})
}
render(){
return (
<form onSubmit={this.uploadMovie}>
<div className="form-group">
<label>Movie Title</label>
<input type="text" className="form-control" placeholder="Enter title"
name="title" value={this.state.title} onChange={this.onChangeMovie}/>
</div>
<div className="form-group">
<label>Date Watched</label>
<input type="date" className="form-control"
name="watched" value={this.state.watched} onChange={this.onChangeMovie}/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
)
}
}
export default AddMovie;
When I change the state to an object
state ={
movieUpload: {
title: "",
watched: ""
}
}
and I change the form to add the object
render(){
return (
<form onSubmit={this.uploadMovie}>
<div className="form-group">
<label>Movie Title</label>
<input type="text" className="form-control" placeholder="Enter title"
name="title" value={this.state.movieUpload.title} onChange={this.onChangeMovie}/>
</div>
<div className="form-group">
<label>Date Watched</label>
<input type="date" className="form-control"
name="watched" value={this.state.movieUpload.watched} onChange={this.onChangeMovie}/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
)
}
The input box no longer works. Why is this and how do I change it?
If you're going to make those changes, you need to change your onChangeMovie as well
onChangeMovie = (e) => {
this.setState({uploadMovie: {...this.state.uploadMovie, [e.target.name] : e.target.value}});
}
This will copy the current this.state.uploadMovie and then overwrite the title/watched.
I have created a form using reactjs now I want to store each submission in an array format
Eg.
item[0]: name:'name1' mail:'asd#sad'
item[1]: name:'name2' mail:'ds#asd'
I want in that array format and how do I achieve that?
I have tried the below code to store the data in array format but whenever I submit it creates new array everything should be stored in a single element
import React from 'react'
import './style.css'
class FormSample extends React.Component{
constructor(props){
super(props);
this.state={
fname:'',
lname:'',
email:'',
subject:'',
data:[]
}
}
handleFormSubmit(event){
event.preventDefault();
let items = [...this.state.data]
items.push({
fname: this.state.fname,
lname: this.state.lname,
email: this.state.email,
subject: this.state.subject
});
this.setState({
items,
// fname:'',
// lname:'',
// email:'',
// subject:'',
})
console.log(this.state)
}
render(){
return(
<div className="formData">
<p>Contact me</p>
<div>
<form action="#">
<label>first name</label>
<input
type="text"
id="fname"
name="firstname"
placeholder="your name..."
value={this.state.fname}
onChange={e => this.setState({fname: e.target.value})}/>
<label>last name</label>
<input
type="text"
id="lname"
name="lastname"
placeholder="last name.."
value={this.state.lname}
onChange={e => this.setState({lname: e.target.value})}/>
<label>Email</label>
<input
type="email"
id="email"
name="email"
placeholder="email"
value={this.state.email}
onChange={e => this.setState({email: e.target.value})}/>
<label>Subject</label>
<textarea
id="subject"
name="subject"
placeholder="write..."
value={this.state.subject}
onChange={e => this.setState({subject: e.target.value})}/>
<input type="submit" value="submit" onClick={e => this.handleFormSubmit(e)}/>
</form>
</div>
</div>
)
}
}
export default FormSample;
The output I got below in the console
After storing in the array format how do I fetch the data to display in the table format?
When setting state depends on previous state, always use an updater function rather than referring to state values directly.
I.e. don't do:
this.setState({myVal: this.state.myVal + 1})
Instead do:
setState(prevState => {myVal: prevState.myVal + 1})
This is due to the way React batches state updates. You can read more about it in the React docs on setting state.
That means that your code should read something like:
handleFormSubmit(event) {
event.preventDefault()
this.setState(prevState => ({
data: [...prevState.data,
{
fname: prevState.fname,
lname: prevState.lname,
email: prevState.email,
subject: prevState.subject
}]
}))
}
Here we are using the spread operator ... to create a new data array filled with the previous data array's values, and appending a new object to the end of it.
I saw on another answer that someone recommended using 'this.state.data.push({})`.
You should never mutate state directly. Array.prototype.push mutates the current array, meaning this is bad bad bad.
Stick with updating state in the correct way, using immutable objects and creating new arrays rather than pushing to existing ones.
To answer your question on how to access data once it's in the array, you just use standard syntax:
const { fname, lname, email, subject } = this.state.data[i]
where i is the index of the data object you are trying to access. I've used the object destructor syntax above because it exposes object properties nicely.
It Will Help You......
<table>
<tr>
<td>name</td>
<td>mail</td
</tr>
data.map((key,value)=>{
<tr key={key}>
<td>{value.name}</td>
<td>{value.name}</td>
</tr>
});
</table>
Do like this then you can store data in Array:-
handleFormSubmit(event) {
debugger;
event.preventDefault();
this.setState({
data: this.state.data.push({
fname: this.state.fname,
lname: this.state.lname,
email: this.state.email,
subject: this.state.subject
})
});
console.log(this.state);
}
render() {
const list = this.state.data;
return (
<div className="formData">
<p>Contact me</p>
<div>
<form action="#">
<label>first name</label>
<input
type="text"
id="fname"
name="firstname"
placeholder="your name..."
value={this.state.fname}
onChange={e => this.setState({ fname: e.target.value })}
/>
<label>last name</label>
<input
type="text"
id="lname"
name="lastname"
placeholder="last name.."
value={this.state.lname}
onChange={e => this.setState({ lname: e.target.value })}
/>
<label>Email</label>
<input
type="email"
id="email"
name="email"
placeholder="email"
value={this.state.email}
onChange={e => this.setState({ email: e.target.value })}
/>
<label>Subject</label>
<textarea
id="subject"
name="subject"
placeholder="write..."
value={this.state.subject}
onChange={e => this.setState({ subject: e.target.value })}
/>
<input
type="submit"
value="submit"
onClick={e => this.handleFormSubmit(e)}
/>
</form>
</div>
<Table data={this.state.data} />
</div>
);
}
And for displaying data in table :-
class Table extends Component {
state = {
list: this.props.data
};
render() {
return (
<div id="Table">
<table>
<thead>
<tr>
<th>fname</th>
<th>lname</th>
</tr>
</thead>
<tbody>
{this.state.list.map(item => {
return (
<tr>
<td>{item.fname}</td>
<td>{item.lname}</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}
}
We're trying to set up a data entry form that adds input to an object in mongo. We're positive this has to do with our front end as we can't get the input data to even print to an alert.
import { Panel, Button,ButtonToolbar} from 'react-bootstrap';
export default class ResearcherPortal extends React.Component {
constructor(props){
super(props);
this.state = {
schoolName: '',
studyName: '',
studyDescription: '',
identifier: '',
numberOfConsenting: null,
numberOfNonconsenting: null
},
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event){
this.setState({numberOfConsenting: event.target.value});
alert(this.state.numberOfConsenting);
}
render() {
return (
<div className="jumbotron">
<div className="container ">
<div className ="row justify-content-md-center">
<Panel bsStyle="primary">
<Panel.Heading>
<h2>Researcher Portal</h2>
</Panel.Heading>
<Panel.Body>
<form id="Account Creation" action={"/researcherPortal"} method="POST">
<div className="form-group">
<input type="text" className="form-control" id="schoolName" placeholder="School Name"/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="studyName" placeholder="Study Name"/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="studyDescription" placeholder="Study Description"/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="identifier" placeholder="Unique Identifier"/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="numberOfConsenting" placeholder="Number of Consenting Students" value={this.state.numberOfConsenting}/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="numberOfNonconsenting" placeholder="Number of Nonconsenting Students"/>
</div>
<Button type="submit" className="btn btn-primary" onClick={this.handleSubmit.bind(this)}>Create Accounts</Button>
</form>
</Panel.Body>
</Panel>
</div>
</div>
</div>
);
}
}
Expected result is the input for "Number of Consenting Students", however we are just outputting the initial constructor value.
You need to provide an onChange to the input whose value is this.state.numberOfConsenting. Something like -
changeNumberOfConsenting(event) {
this.setState({ numberOfConsenting: event.target.value });
}
...
<input ... value={this.state.numberOfConsenting} onChange={this.changeNumberOfConsenting} />
and then bind it in your constructor like you did for handleSubmit.
Use refs.
Add handler to constructor:
this.consentingStudents = React.createRef();
Add this ref for needed input:
<input type="text" className="form-control" id="numberOfConsenting" placeholder="Number of Consenting Students" ref={this.consentingStudents} value={this.state.numberOfConsenting} />
And get its value in the handleSubmit():
handleSubmit(event) {
this.setState({ numberOfConsenting: this.consentingStudents.current.value });
alert(this.consentingStudents.current.value);
}
I'm very new to react, and following a tutorial, made this Registration form (I just changed Bootstrap html with Materialize)
import React, {Component} from 'react';
class Register extends Component {
constructor() {
super();
this.state = {
email: '',
password: '',
errors: {}
};
this.handleChange = this.handleChange.bind(this);
}
handleChange (e) {
this.setState({
[e.target.name] : e.target.value
});
}
render() {
return (
<div>
<div className="row">
<div className="col s10 m6 offset-s1 offset-m3 ">
<form className="col s12 myform">
<h3 className="center"Register </h3>
<div className="row">
<div className="input-field col s12">
<input
id="email"
type="email"
value={this.state.email}
onChange = {this.handleChange}
/>
<label htmlFor="email">Email</label>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<input
id="password"
type="password"
value={this.state.password}
onChange = {this.handleChange}
/>
<label htmlFor="password">Password</label>
</div>
</div>
<button className="btn mybtn waves-effect waves-light right" type="submit" name="action">Submit
<i className="mdi-content-send right"></i>
</button>
</form>
</div>
</div>
</div>
);
}
}
export default Register;
The problem is that I can not enter anything into the form and get no error in the console. So got really preplexed. Appreciate your hints.
As you have written:
handleChange (e) {
this.setState({
[e.target.name] : e.target.value // This line I mean.
});
}
So you just need to assign name prop to input tag because you have written e.target.name and your input name is available in the state but not available in input props.
So do it like this:
- Email input
<input
name="email"
id="email"
type="email"
value={this.state.email}
onChange = {this.handleChange}
/>
- Password input
<input
name="email"
id="email"
type="email"
value={this.state.email}
onChange = {this.handleChange}
/>
I hope it will be helped you and enjoy of react