Template doesn't react to the change of variable React - reactjs

I have a component in which I want to display another component after form submit.
When I'm running function on form submit I'm changing submitted value to true and if I do console.log(submitted) it changes to true but in the template it is still false so Alert component doesn't show up.
I'm trying to learn hooks and maybe the problem with how I'm using them?
My component looks like this
export const SignupForm = () => {
let name:any = handleUserInput('');
let email:any = handleUserInput('');
let password:any = handleUserInput('');
let submitted:any = false;
function registerUser(event: React.FormEvent<HTMLFormElement>): void {
event.preventDefault();
submitted = true;
const registerInfo = Object.assign({}, {
email: email.value,
password: password.value,
name: name.value
});
axios.post('/register', registerInfo)
.then(response => {
errors = response.data.errors
})
.catch(error => console.log(error))
}
function handleUserInput(initialValue: string): object {
const [value, setValue] = useState(initialValue);
function handleChange(event: Event): void {
let element = event.target as HTMLInputElement;
setValue(element.value);
}
return {
value,
onChange: handleChange
}
}
return (
<div>
<div dangerouslySetInnerHTML={{__html: submitted}}></div>
{submitted ? <Alert /> : ''}
<div className="form-holder">
<form action="POST" className="form" onSubmit={(e) => registerUser(e)}>
<label htmlFor="Email">Email</label>
<input type="text" id="email" className="form__input" {...email} required />
<label htmlFor="password">Password</label>
<input type="password" id="password" className="form__input" {...password} required />
<label htmlFor="name">Name</label>
<input type="text" id="name" className="form__input" {...name} required />
<button type="submit" className="form__button">Signup</button>
</form>
</div>
</div>
);
}

submitted local variable is assigned asynchronously. This won't result in component update.
It should be:
...
const [submitted, setSubmitted] = useState(false);
function registerUser(event: React.FormEvent<HTMLFormElement>): void {
event.preventDefault();
setSubmitted(true);
...

Related

remove the value enterd in input fild after submistion :react js [duplicate]

I have a form containing various input fields and two buttons; one for submitting and one for cancelling.
<form id="create-course-form">
<input type="text" name="course_Name" ref="fieldName">
<input type="text" name="course_org" ref="fieldOrg">
<input type="text" name="course_Number" ref="fieldNum">
<input type="submit" name="saveCourse" value="Create">
<input type="button" name="cancelCourse" value="cancel" onClick={this.cancelCourse}>
</form>
What I want is to empty all inputs when the cancel button is clicked. So far I've managed to do this by using each input's ref prop.
cancelCourse(){
this.refs.fieldName.value="";
this.refs.fieldorg.value="";
this.refs.fieldNum.value="";
}
However, I want to empty the input fields without having to empty each one seperately. I want something similar to this (jQuery): $('#create-course-form input[type=text]').val('');
The answer here depends on whether or not your inputs are controlled or uncontrolled. If you are unsure or need more info on this, check out what the official docs say about controlled components and uncontrolled components. Thanks #Dan-Esparza for providing the links.
Also, please note that using string literals in ref is deprecated. Use the standard callback method instead.
Clearing a form with uncontrolled fields
You can clear the entire form rather than each form field individually.
cancelCourse = () => {
document.getElementById("create-course-form").reset();
}
render() {
return (
<form id="create-course-form">
<input />
<input />
...
<input />
</form>
);
}
If your form didn't have an id attribute you could use a ref as well:
cancelCourse = () => {
this.myFormRef.reset();
}
render() {
return (
<form ref={(el) => this.myFormRef = el;}>
<input />
<input />
...
<input />
</form>
);
}
Clearing a form with controlled fields
If you are using controlled form fields, you may have to explicitly reset each component inside your form, depending on how your values are stored in the state.
If they are declared individually, you need to reset each one explicitly:
cancelCourse = () => {
this.setState({
inputVal_1: "",
inputVal_2: "",
...
inputVal_n: "",
});
}
render() {
return (
<input value={this.state.inputVal_1} onChange={this.handleInput1Change}>
<input value={this.state.inputVal_2} onChange={this.handleInput2Change}>
...
<input value={this.state.inputVal_n} onChange={this.handleInputnChange}>
);
}
Demo below:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
inputVal_1: "",
inputVal_2: "",
inputVal_3: "",
inputVal_4: "",
inputVal_5: "",
inputVal_6: "",
inputVal_7: "",
inputVal_8: "",
inputVal_9: "",
inputVal_10: ""
};
}
handleInput1Change = (e) => {
this.setState({inputVal_1: e.target.value});
}
handleInput2Change = (e) => {
this.setState({inputVal_2: e.target.value});
}
handleInput3Change = (e) => {
this.setState({inputVal_3: e.target.value});
}
handleInput4Change = (e) => {
this.setState({inputVal_4: e.target.value});
}
handleInput5Change = (e) => {
this.setState({inputVal_5: e.target.value});
}
handleInput6Change = (e) => {
this.setState({inputVal_6: e.target.value});
}
handleInput7Change = (e) => {
this.setState({inputVal_7: e.target.value});
}
handleInput8Change = (e) => {
this.setState({inputVal_8: e.target.value});
}
handleInput9Change = (e) => {
this.setState({inputVal_9: e.target.value});
}
handleInput10Change = (e) => {
this.setState({inputVal_10: e.target.value});
}
cancelCourse = () => {
this.setState({
inputVal_1: "",
inputVal_2: "",
inputVal_3: "",
inputVal_4: "",
inputVal_5: "",
inputVal_6: "",
inputVal_7: "",
inputVal_8: "",
inputVal_9: "",
inputVal_10: ""
});
}
render() {
return (
<form>
<input value={this.state.inputVal_1} onChange={this.handleInput1Change} />
<input value={this.state.inputVal_2} onChange={this.handleInput2Change} />
<input value={this.state.inputVal_3} onChange={this.handleInput3Change} />
<input value={this.state.inputVal_4} onChange={this.handleInput4Change} />
<input value={this.state.inputVal_5} onChange={this.handleInput5Change} />
<input value={this.state.inputVal_6} onChange={this.handleInput6Change} />
<input value={this.state.inputVal_7} onChange={this.handleInput7Change} />
<input value={this.state.inputVal_8} onChange={this.handleInput8Change} />
<input value={this.state.inputVal_9} onChange={this.handleInput9Change} />
<input value={this.state.inputVal_10} onChange={this.handleInput10Change} />
<input type="submit" name="saveCourse" value="Create" />
<input type="button" name="cancelCourse" value="cancel" onClick={this.cancelCourse} />
</form>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
There is a cleaner way to do this though. Rather than having n state properties and n event handlers, one for each input, with some clever coding we can reduce the code dramatically.
In the constructor we just declare an empty object, which will be used to hold input values. We use only one input handler and pass it the index of the input element we want to change the value of. This means that the value of an individual input is generated the moment we start typing into it.
To reset the form, we only need to set our input object back to being empty again.
The input value is this.state.inputVal[i]. If i doesn't exist (we haven't typed anything yet into that input) we want the value to be an empty string (instead of null).
cancelCourse = () => {
this.setState({inputVal: {}});
}
render() {
return (
<form>
{[...Array(n)].map(
(item, i) => <input value={this.state.inputVal[i] || ""} onChange={this.handleInputChange.bind(this, i)} />
)}
</form>
);
}
Demo below:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
inputVal: {}
};
}
handleInputChange = (idx, {target}) => {
this.setState(({inputVal}) => {
inputVal[idx] = target.value;
return inputVal;
});
}
cancelCourse = () => {
this.setState({inputVal: {}});
}
render() {
return(
<form>
{[...Array(10)].map( //create an array with a length of 10
(item, i) => <input value={this.state.inputVal[i] || ""} onChange={this.handleInputChange.bind(this, i)} /> //bind the index to the input handler
)}
<input type="submit" name="saveCourse" value="Create" />
<input type="button" name="cancelCourse" value="cancel" onClick={this.cancelCourse} />
</form>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Very easy:
handleSubmit(e){
e.preventDefault();
e.target.reset();
}
// If using class component
<form onSubmit={this.handleSubmit.bind(this)}>
...
</form>
// If using function component
<form onSubmit={handleSubmit}>
...
</form>
Using event.target.reset() only works for uncontrolled components, which is not recommended. For controlled components you would do something like this:
import React, { Component } from 'react'
class MyForm extends Component {
initialState = { name: '' }
state = this.initialState
handleFormReset = () => {
this.setState(() => this.initialState)
}
render() {
return (
<form onReset={this.handleFormReset}>
<div>
<label htmlFor="name">Name</label>
<input
type="text"
placeholder="Enter name"
name="name"
value={name}
onChange={this.handleInputOnChange}
/>
</div>
<div>
<input
type="submit"
value="Submit"
/>
<input
type="reset"
value="Reset"
/>
</div>
</form>
)
}
}
ContactAdd.propTypes = {}
export default MyForm
You can also do it by targeting the current input, with anything.target.reset() . This is the most easiest way!
handleSubmit(e){
e.preventDefault();
e.target.reset();
}
<form onSubmit={this.handleSubmit}>
...
</form>
Here's an update to Chris's answer above, using modern React hooks.
Same high level idea; your form can be either a Controlled or Uncontrolled component.
Uncontrolled components:
Uncontrolled components leave state management up to the browser. That means you have to ask the browser to reset the form inputs. To do that, capture the form element as a ref, and then call the submit() method on that element.
export default function Form() {
const ref = React.useRef();
function reset(ev) {
ev.preventDefault();
ref.current.reset();
}
return (
<form ref={ref}>
<label htmlFor="email">Email Address</label>
<input id="email" type="email" name="email" />
<label htmlFor="message">Message</label>
<textarea id="message" name="message" />
<button type="submit">Submit</button>
<button onClick={reset}>Reset</button>
</form>
);
}
Controlled components:
With a controlled component, you manage the state in React. That means you have to create the initial state, and update it every time an input changes. In this world, resetting the form is just a matter of setting the form state back to its initial state.
export default function Form() {
const [state, setState] = React.useState({ email: "", message: "" });
function reset(ev) {
ev.preventDefault();
setState({ email: "", message: "" });
}
return (
<form className="Form">
<label htmlFor="email">Email Address</label>
<input
id="email"
type="email"
name="email"
value={state.email}
onChange={(ev) => {
setState({ ...state, email: ev.target.value });
}}
/>
<label htmlFor="message">Message</label>
<textarea
id="message"
name="message"
value={state.message}
onChange={(ev) => {
setState({ ...state, message: ev.target.value });
}}
/>
<button type="submit">Submit</button>
<button onClick={reset}>Reset</button>
</form>
);
}
Full example at https://codesandbox.io/s/reactformreset-10cjn3
Following code should reset the form in one click.
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.handleSubmit=this.handleSubmit.bind(this);
}
handleSubmit(e){
this.refs.form.reset();
}
render(){
return(
<div>
<form onSubmit={this.handleSubmit} ref="form">
<input type="text" placeholder="First Name!" ref='firstName'/><br/<br/>
<input type="text" placeholder="Last Name!" ref='lastName'/><br/><br/>
<button type="submit" >submit</button>
</form>
</div>
}
}
To clear your form, admitted that your form's elements values are saved in your state, you can map through your state like that :
// clear all your form
Object.keys(this.state).map((key, index) => {
this.setState({[key] : ""});
});
If your form is among other fields, you can simply insert them in a particular field of the state like that:
state={
form: {
name:"",
email:""}
}
// handle set in nested objects
handleChange = (e) =>{
e.preventDefault();
const newState = Object.assign({}, this.state);
newState.form[e.target.name] = e.target.value;
this.setState(newState);
}
// submit and clear state in nested object
onSubmit = (e) =>{
e.preventDefault();
var form = Object.assign({}, this.state.form);
Object.keys(form).map((key, index) => {
form[key] = "" ;
});
this.setState({form})
}
This one works best to reset the form.
import React, { Component } from 'react'
class MyComponent extends Component {
constructor(props){
super(props)
this.state = {
inputVal: props.inputValue
}
// preserve the initial state in a new object
this.baseState = this.state ///>>>>>>>>> note this one.
}
resetForm = () => {
this.setState(this.baseState) ///>>>>>>>>> note this one.
}
submitForm = () => {
// submit the form logic
}
updateInput = val => this.setState({ inputVal: val })
render() {
return (
<form>
<input
onChange={this.updateInput}
type="text
value={this.state.inputVal} />
<button
onClick={this.resetForm}
type="button">Cancel</button>
<button
onClick={this.submitForm}
type="submit">Submit</button>
</form>
)
}
}
When the form is submitted, the 'event' will be passed as an argument to the handleSubmit method, and if that you can access the <form> element by typing event.target. then you just need to reset the form using .reset() form method.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset
handleSubmit = (event)=>{
event.preventDefault()
....
event.target.reset()
}
render() {
return (
<>
<form onSubmit={this.handleSubmit}>
<label htmlFor='movieTitle'>Title</label>
<input name='movieTitle' id='movieTitle' type='text' />
<input type='submit' value='Find Movie Info' />
</form>
</>
)
}
I don't know if this is still relevant. But when I had similar issue this is how I resolved it.
Where you need to clear an uncontrolled form you simply do this after submission.
this.<ref-name-goes-here>.setState({value: ''});
Hope this helps.
import React, { Component } from 'react'
export default class Form extends Component {
constructor(props) {
super(props)
this.formRef = React.createRef()
this.state = {
email: '',
loading: false,
eror: null
}
}
reset = () => {
this.formRef.current.reset()
}
render() {
return (
<div>
<form>
<input type="email" name="" id=""/>
<button type="submit">Submit</button>
<button onClick={()=>this.reset()}>Reset</button>
</form>
</div>
)
}
}
/*
See newState and use of it in eventSubmit() for resetting all the state.
I have tested it is working for me. Please let me know for mistakes
*/
import React from 'react';
const newState = {
fullname: '',
email: ''
}
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
fullname: ' ',
email: ' '
}
this.eventChange = this
.eventChange
.bind(this);
this.eventSubmit = this
.eventSubmit
.bind(this);
}
eventChange(event) {
const target = event.target;
const value = target.type === 'checkbox'
? target.type
: target.value;
const name = target.name;
this.setState({[name]: value})
}
eventSubmit(event) {
alert(JSON.stringify(this.state))
event.preventDefault();
this.setState({...newState});
}
render() {
return (
<div className="container">
<form className="row mt-5" onSubmit={this.eventSubmit}>
<label className="col-md-12">
Full Name
<input
type="text"
name="fullname"
id="fullname"
value={this.state.fullname}
onChange={this.eventChange}/>
</label>
<label className="col-md-12">
email
<input
type="text"
name="email"
id="email"
value={this.state.value}
onChange={this.eventChange}/>
</label>
<input type="submit" value="Submit"/>
</form>
</div>
)
}
}
export default Form;
the easiest way is doing it regularly with just HTML and using the button type "reset" there is no need to mess with anything in react at all, no state, no nothing.
import React, {useState} from 'react'
function HowReactWorks() {
return (
<div>
<form>
<div>
<label for="name">Name</label>
<input type="text" id="name" placeholder="name" />
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" placeholder="password" />
</div>
<button type="reset">Reset</button>
<button>Submit</button>
</form>
</div>
)
}
export default HowReactWorks
edited for the people that don't know how to include HTML in react
You can use this method as well
const resetData = (e) => {
e.preventDefault();
settitle("");
setdate("");
};
<input type="text" onChange={(e) => settitle(e.target.value)} value={title} />
<input type="date" onChange={(e) => setdate(e.target.value)} value={date} />
<button onClick={resetData}>Reset Data</button>
This is the solution that worked for me, in the case of parent component triggering reset of child controlled input components:
const ParentComponent = () => {
const [reset, setReset] = useState()
const submitHandler = (e) => {
e.preventDefault()
//do your stuff
setReset(Date.now()) // pass some value to trigger update
}
return (
<form onSubmit={submitHandler}>
<ChildInputComponent reset={reset} />
<ChildInputComponent reset={reset} />
</form>
)
}
const ChildInputComponent = ({reset}) => {
const [value, setValue] = useState()
useEffect(() => {
setValue('')
}, [reset])
return <input value={value} onChange={(e) => setValue(e.target.value)} />
}
Assuming you declared
const [inputs, setInputs] = useState([]);
As multiple parameters. You can actually reset the items using this syntax:
setInputs([]);
Just in case, this how you define handleChange.
You can use this form or any ways you want.
const handleChange = (event) => {
const name = event.target.name;
const email = event.target.email;
const message = event.target.message;
const value = event.target.value;
setInputs(values => ({...values, [name]: value, [email]: value, [message]: value}))
}
You can use this form as an example.
<form onSubmit={handleSubmit}>
<div className="fields">
<div className="field half">
<label for="name">Name</label>
<input value={inputs.name || ''} type="text" name="name" id="nameId" onChange={handleChange} maxLength="30" />
</div>
<div className="field half">
<label for="email">Email</label>
<input value={inputs.email || ''} type="text" name="email" id="emailId" onChange={handleChange} maxLength="40"/>
</div>
<div className="field">
<label for="message">Message</label>
<textarea value={inputs.message || ''} name="message" id="messageId" rows="6" onChange={handleChange} maxLength="400" />
</div>
</div>
<ul className="actions">
<li><input type="submit" value="Send Message" className="primary" /></li>
<li><input onClick={resetDetails} type="reset" value="Clear" /></li>
</ul>
</form>
This is just one of many ways to declare forms. Good luck!
const onReset = () => {
form.resetFields();
};
state={
name:"",
email:""
}
handalSubmit = () => {
after api call
let resetFrom = {}
fetch('url')
.then(function(response) {
if(response.success){
resetFrom{
name:"",
email:""
}
}
})
this.setState({...resetFrom})
}
Why not use HTML-controlled items such as <input type="reset">

React: How to clear file input and data input fields after submitting form?

After I submit my form, which contains data fields and a file field, only the data fields are cleared, but the uploaded file field is kept. See image: Here
OnChange Function
onChange = (e) => {
if(e.target.name === 'audio') {
this.setState({
[e.target.name]: e.target.files[0], loaded: 0,
}, () => console.log(this.state.audio))
} else {
this.setState({
[e.target.name]: e.target.value
}, () => console.log(this.state))
}
}
Submit Function
onSubmit = e => {
e.preventDefault();
let { title, content, audio} = this.state;
//const story = { title, content, audio};
let formDataStory = new FormData();
formDataStory.append('audio', audio);
formDataStory.append('title', title);
formDataStory.append('content', content);
this.props.addStory(formDataStory);
this.setState({
title: "",
content:"",
audio: ""
});
};
Form
render() {
const {title, content, audio} = this.state;
return (
<div className="card card-body mt-4 mb-4">
<h2>Add Story</h2>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Title</label>
<input
className="form-control"
type="text"
name="title"
onChange={this.onChange}
value={title}
/>
</div>
<div className="form-group">
<label>Content</label>
<input
className="form-control"
type="text"
name="content"
onChange={this.onChange}
value={content}
/>
</div>
<div className="form-group">
<label>Audio</label>
<input
className="form-control"
type="file"
name="audio"
onChange={this.onChange}
//value={audio}
/>
</div>
<div className="form-group">
<button type="submit" className="btn btn-primary">
Submit
</button>
</div>
</form>
</div>
);
}
}
How can I reset the file upload field together with the other data fields after submitting the form?
Many thanks!
Since the file input is always uncontrolled you'll need to use a dom ref and manually clear the value.
Here's an example functional component that does this:
function ExampleFileInput() {
const ref = React.useRef();
function handleClick() {
ref.current.value = ""
}
return (
<div className="App">
<input type="file" ref={ref}/><br />
<button type="button" onClick={handleClick}>Clear file</button>
</div>
);
}
To use in a class component, see the docs. You can read about more ways to clear the file input in this question.
Docs
Create ref to file input this.inputRef = React.createRef();
add ref to input <input type="file" ref={this.inputRef} />
Inside submit function this.inputRef.current.value = '';
If you use Formik you can do this:
I had the same issue and I managed it creating a ref in the parent component (the one that use Formik) and passing it to the Field using innerRef prop.
Then on the onReset I used the ref to clear the real input value.
const UserForm = props => {
const logoRef = useRef();
const handleReset = (values, formikBag) => {
logoRef.current.value = null; //THIS RESETS THE FILE FIELD
}
const handleSubmit = (values, formikBag) => {
//...
axios({method, url, data})
.then(response => {
formikBag.resetForm();
})
}
//...
return (
<Formik initialValues={initialValues} onSubmit={handleSubmit} onReset={handleReset}>
...
<Field
type="file"
name="logo"
onChange={({target}) => setFieldValue(props.name, target.files[0])}
innerRef={logoRef}
/>
</Formik>
)
}

the state inside hooks are not updated for first time on form submit in react

I was trying to implement contactUS form in react using hooks.Contact us form is placed inside hooks.When I first submit the form the state in hooks are not updated ,when I click 2nd time states are set .and I am returning state to class component there api call are made.
//contactushook.js
import React, { useState } from 'react';
const ContactUshook = ({ parentCallBack }) => {
const [data, setData] = useState([]);
const handleSubmit = (event) => {
event.preventDefault();
setData({ name: document.getElementById('name').value, email: document.getElementById('email').value, message: document.getElementById('message').value });
console.log(data);
parentCallBack(data);
}
return <React.Fragment>
<div className="form-holder">
<form onSubmit={handleSubmit}>
<div>
<input id="name" type="text" placeholder="enter the name"></input>
</div>
<div>
<input id="email" type="email" placeholder="enter the email"></input>
</div>
<div>
<textarea id="message" placeholder="Type message here"></textarea>
</div>
<button type="submit" >Submit</button>
</form>
</div>
</React.Fragment >
}
export default ContactUshook;
//contactus.js
import React, { Component } from 'react';
import ContactUshook from './hooks/contactushook';
import '../contactUs/contactus.css';
class ContactComponent extends Component {
onSubmit = (data) => {
console.log('in onsubmit');
console.log(data);
}
render() {
return (
<div>
<h4>hook</h4>
<ContactUshook parentCallBack={this.onSubmit}></ContactUshook>
</div>
);
}
}
export default ContactComponent;
Stop using document queries and start using state instead!
Your ContactUshook component should look like this:
const ContactUshook = ({ parentCallBack }) => {
const [data, setData] = useState({ name: '', email: '', message: '' });
const handleSubmit = () => {
event.preventDefault();
parentCallBack(data);
}
const handleChange = (event, field) => {
const newData = { ...data };
newData[field] = event.target.value;
setData(newData);
}
return (
<div className="form-holder">
<form onSubmit={handleSubmit}>
<div>
<input
id="name"
type="text"
value={data.name}
placeholder="enter the name"
onChange={(e) => handleChange(e,'name')} />
</div>
<div>
<input
id="email"
type="email"
value={data.email}
placeholder="enter the email"
onChange={(e) => handleChange(e,'email')} />
</div>
<div>
<textarea
id="message"
value={data.message}
placeholder="Type message here"
onChange={(e) => handleChange(e,'message')} />
</div>
<button type="submit" >Submit</button>
</form>
</div>
);
}

Clear and reset form input fields

I have a form containing various input fields and two buttons; one for submitting and one for cancelling.
<form id="create-course-form">
<input type="text" name="course_Name" ref="fieldName">
<input type="text" name="course_org" ref="fieldOrg">
<input type="text" name="course_Number" ref="fieldNum">
<input type="submit" name="saveCourse" value="Create">
<input type="button" name="cancelCourse" value="cancel" onClick={this.cancelCourse}>
</form>
What I want is to empty all inputs when the cancel button is clicked. So far I've managed to do this by using each input's ref prop.
cancelCourse(){
this.refs.fieldName.value="";
this.refs.fieldorg.value="";
this.refs.fieldNum.value="";
}
However, I want to empty the input fields without having to empty each one seperately. I want something similar to this (jQuery): $('#create-course-form input[type=text]').val('');
The answer here depends on whether or not your inputs are controlled or uncontrolled. If you are unsure or need more info on this, check out what the official docs say about controlled components and uncontrolled components. Thanks #Dan-Esparza for providing the links.
Also, please note that using string literals in ref is deprecated. Use the standard callback method instead.
Clearing a form with uncontrolled fields
You can clear the entire form rather than each form field individually.
cancelCourse = () => {
document.getElementById("create-course-form").reset();
}
render() {
return (
<form id="create-course-form">
<input />
<input />
...
<input />
</form>
);
}
If your form didn't have an id attribute you could use a ref as well:
cancelCourse = () => {
this.myFormRef.reset();
}
render() {
return (
<form ref={(el) => this.myFormRef = el;}>
<input />
<input />
...
<input />
</form>
);
}
Clearing a form with controlled fields
If you are using controlled form fields, you may have to explicitly reset each component inside your form, depending on how your values are stored in the state.
If they are declared individually, you need to reset each one explicitly:
cancelCourse = () => {
this.setState({
inputVal_1: "",
inputVal_2: "",
...
inputVal_n: "",
});
}
render() {
return (
<input value={this.state.inputVal_1} onChange={this.handleInput1Change}>
<input value={this.state.inputVal_2} onChange={this.handleInput2Change}>
...
<input value={this.state.inputVal_n} onChange={this.handleInputnChange}>
);
}
Demo below:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
inputVal_1: "",
inputVal_2: "",
inputVal_3: "",
inputVal_4: "",
inputVal_5: "",
inputVal_6: "",
inputVal_7: "",
inputVal_8: "",
inputVal_9: "",
inputVal_10: ""
};
}
handleInput1Change = (e) => {
this.setState({inputVal_1: e.target.value});
}
handleInput2Change = (e) => {
this.setState({inputVal_2: e.target.value});
}
handleInput3Change = (e) => {
this.setState({inputVal_3: e.target.value});
}
handleInput4Change = (e) => {
this.setState({inputVal_4: e.target.value});
}
handleInput5Change = (e) => {
this.setState({inputVal_5: e.target.value});
}
handleInput6Change = (e) => {
this.setState({inputVal_6: e.target.value});
}
handleInput7Change = (e) => {
this.setState({inputVal_7: e.target.value});
}
handleInput8Change = (e) => {
this.setState({inputVal_8: e.target.value});
}
handleInput9Change = (e) => {
this.setState({inputVal_9: e.target.value});
}
handleInput10Change = (e) => {
this.setState({inputVal_10: e.target.value});
}
cancelCourse = () => {
this.setState({
inputVal_1: "",
inputVal_2: "",
inputVal_3: "",
inputVal_4: "",
inputVal_5: "",
inputVal_6: "",
inputVal_7: "",
inputVal_8: "",
inputVal_9: "",
inputVal_10: ""
});
}
render() {
return (
<form>
<input value={this.state.inputVal_1} onChange={this.handleInput1Change} />
<input value={this.state.inputVal_2} onChange={this.handleInput2Change} />
<input value={this.state.inputVal_3} onChange={this.handleInput3Change} />
<input value={this.state.inputVal_4} onChange={this.handleInput4Change} />
<input value={this.state.inputVal_5} onChange={this.handleInput5Change} />
<input value={this.state.inputVal_6} onChange={this.handleInput6Change} />
<input value={this.state.inputVal_7} onChange={this.handleInput7Change} />
<input value={this.state.inputVal_8} onChange={this.handleInput8Change} />
<input value={this.state.inputVal_9} onChange={this.handleInput9Change} />
<input value={this.state.inputVal_10} onChange={this.handleInput10Change} />
<input type="submit" name="saveCourse" value="Create" />
<input type="button" name="cancelCourse" value="cancel" onClick={this.cancelCourse} />
</form>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
There is a cleaner way to do this though. Rather than having n state properties and n event handlers, one for each input, with some clever coding we can reduce the code dramatically.
In the constructor we just declare an empty object, which will be used to hold input values. We use only one input handler and pass it the index of the input element we want to change the value of. This means that the value of an individual input is generated the moment we start typing into it.
To reset the form, we only need to set our input object back to being empty again.
The input value is this.state.inputVal[i]. If i doesn't exist (we haven't typed anything yet into that input) we want the value to be an empty string (instead of null).
cancelCourse = () => {
this.setState({inputVal: {}});
}
render() {
return (
<form>
{[...Array(n)].map(
(item, i) => <input value={this.state.inputVal[i] || ""} onChange={this.handleInputChange.bind(this, i)} />
)}
</form>
);
}
Demo below:
class MyApp extends React.Component {
constructor() {
super();
this.state = {
inputVal: {}
};
}
handleInputChange = (idx, {target}) => {
this.setState(({inputVal}) => {
inputVal[idx] = target.value;
return inputVal;
});
}
cancelCourse = () => {
this.setState({inputVal: {}});
}
render() {
return(
<form>
{[...Array(10)].map( //create an array with a length of 10
(item, i) => <input value={this.state.inputVal[i] || ""} onChange={this.handleInputChange.bind(this, i)} /> //bind the index to the input handler
)}
<input type="submit" name="saveCourse" value="Create" />
<input type="button" name="cancelCourse" value="cancel" onClick={this.cancelCourse} />
</form>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Very easy:
handleSubmit(e){
e.preventDefault();
e.target.reset();
}
// If using class component
<form onSubmit={this.handleSubmit.bind(this)}>
...
</form>
// If using function component
<form onSubmit={handleSubmit}>
...
</form>
Using event.target.reset() only works for uncontrolled components, which is not recommended. For controlled components you would do something like this:
import React, { Component } from 'react'
class MyForm extends Component {
initialState = { name: '' }
state = this.initialState
handleFormReset = () => {
this.setState(() => this.initialState)
}
render() {
return (
<form onReset={this.handleFormReset}>
<div>
<label htmlFor="name">Name</label>
<input
type="text"
placeholder="Enter name"
name="name"
value={name}
onChange={this.handleInputOnChange}
/>
</div>
<div>
<input
type="submit"
value="Submit"
/>
<input
type="reset"
value="Reset"
/>
</div>
</form>
)
}
}
ContactAdd.propTypes = {}
export default MyForm
You can also do it by targeting the current input, with anything.target.reset() . This is the most easiest way!
handleSubmit(e){
e.preventDefault();
e.target.reset();
}
<form onSubmit={this.handleSubmit}>
...
</form>
Here's an update to Chris's answer above, using modern React hooks.
Same high level idea; your form can be either a Controlled or Uncontrolled component.
Uncontrolled components:
Uncontrolled components leave state management up to the browser. That means you have to ask the browser to reset the form inputs. To do that, capture the form element as a ref, and then call the submit() method on that element.
export default function Form() {
const ref = React.useRef();
function reset(ev) {
ev.preventDefault();
ref.current.reset();
}
return (
<form ref={ref}>
<label htmlFor="email">Email Address</label>
<input id="email" type="email" name="email" />
<label htmlFor="message">Message</label>
<textarea id="message" name="message" />
<button type="submit">Submit</button>
<button onClick={reset}>Reset</button>
</form>
);
}
Controlled components:
With a controlled component, you manage the state in React. That means you have to create the initial state, and update it every time an input changes. In this world, resetting the form is just a matter of setting the form state back to its initial state.
export default function Form() {
const [state, setState] = React.useState({ email: "", message: "" });
function reset(ev) {
ev.preventDefault();
setState({ email: "", message: "" });
}
return (
<form className="Form">
<label htmlFor="email">Email Address</label>
<input
id="email"
type="email"
name="email"
value={state.email}
onChange={(ev) => {
setState({ ...state, email: ev.target.value });
}}
/>
<label htmlFor="message">Message</label>
<textarea
id="message"
name="message"
value={state.message}
onChange={(ev) => {
setState({ ...state, message: ev.target.value });
}}
/>
<button type="submit">Submit</button>
<button onClick={reset}>Reset</button>
</form>
);
}
Full example at https://codesandbox.io/s/reactformreset-10cjn3
Following code should reset the form in one click.
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.handleSubmit=this.handleSubmit.bind(this);
}
handleSubmit(e){
this.refs.form.reset();
}
render(){
return(
<div>
<form onSubmit={this.handleSubmit} ref="form">
<input type="text" placeholder="First Name!" ref='firstName'/><br/<br/>
<input type="text" placeholder="Last Name!" ref='lastName'/><br/><br/>
<button type="submit" >submit</button>
</form>
</div>
}
}
To clear your form, admitted that your form's elements values are saved in your state, you can map through your state like that :
// clear all your form
Object.keys(this.state).map((key, index) => {
this.setState({[key] : ""});
});
If your form is among other fields, you can simply insert them in a particular field of the state like that:
state={
form: {
name:"",
email:""}
}
// handle set in nested objects
handleChange = (e) =>{
e.preventDefault();
const newState = Object.assign({}, this.state);
newState.form[e.target.name] = e.target.value;
this.setState(newState);
}
// submit and clear state in nested object
onSubmit = (e) =>{
e.preventDefault();
var form = Object.assign({}, this.state.form);
Object.keys(form).map((key, index) => {
form[key] = "" ;
});
this.setState({form})
}
This one works best to reset the form.
import React, { Component } from 'react'
class MyComponent extends Component {
constructor(props){
super(props)
this.state = {
inputVal: props.inputValue
}
// preserve the initial state in a new object
this.baseState = this.state ///>>>>>>>>> note this one.
}
resetForm = () => {
this.setState(this.baseState) ///>>>>>>>>> note this one.
}
submitForm = () => {
// submit the form logic
}
updateInput = val => this.setState({ inputVal: val })
render() {
return (
<form>
<input
onChange={this.updateInput}
type="text
value={this.state.inputVal} />
<button
onClick={this.resetForm}
type="button">Cancel</button>
<button
onClick={this.submitForm}
type="submit">Submit</button>
</form>
)
}
}
When the form is submitted, the 'event' will be passed as an argument to the handleSubmit method, and if that you can access the <form> element by typing event.target. then you just need to reset the form using .reset() form method.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset
handleSubmit = (event)=>{
event.preventDefault()
....
event.target.reset()
}
render() {
return (
<>
<form onSubmit={this.handleSubmit}>
<label htmlFor='movieTitle'>Title</label>
<input name='movieTitle' id='movieTitle' type='text' />
<input type='submit' value='Find Movie Info' />
</form>
</>
)
}
I don't know if this is still relevant. But when I had similar issue this is how I resolved it.
Where you need to clear an uncontrolled form you simply do this after submission.
this.<ref-name-goes-here>.setState({value: ''});
Hope this helps.
import React, { Component } from 'react'
export default class Form extends Component {
constructor(props) {
super(props)
this.formRef = React.createRef()
this.state = {
email: '',
loading: false,
eror: null
}
}
reset = () => {
this.formRef.current.reset()
}
render() {
return (
<div>
<form>
<input type="email" name="" id=""/>
<button type="submit">Submit</button>
<button onClick={()=>this.reset()}>Reset</button>
</form>
</div>
)
}
}
/*
See newState and use of it in eventSubmit() for resetting all the state.
I have tested it is working for me. Please let me know for mistakes
*/
import React from 'react';
const newState = {
fullname: '',
email: ''
}
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
fullname: ' ',
email: ' '
}
this.eventChange = this
.eventChange
.bind(this);
this.eventSubmit = this
.eventSubmit
.bind(this);
}
eventChange(event) {
const target = event.target;
const value = target.type === 'checkbox'
? target.type
: target.value;
const name = target.name;
this.setState({[name]: value})
}
eventSubmit(event) {
alert(JSON.stringify(this.state))
event.preventDefault();
this.setState({...newState});
}
render() {
return (
<div className="container">
<form className="row mt-5" onSubmit={this.eventSubmit}>
<label className="col-md-12">
Full Name
<input
type="text"
name="fullname"
id="fullname"
value={this.state.fullname}
onChange={this.eventChange}/>
</label>
<label className="col-md-12">
email
<input
type="text"
name="email"
id="email"
value={this.state.value}
onChange={this.eventChange}/>
</label>
<input type="submit" value="Submit"/>
</form>
</div>
)
}
}
export default Form;
the easiest way is doing it regularly with just HTML and using the button type "reset" there is no need to mess with anything in react at all, no state, no nothing.
import React, {useState} from 'react'
function HowReactWorks() {
return (
<div>
<form>
<div>
<label for="name">Name</label>
<input type="text" id="name" placeholder="name" />
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" placeholder="password" />
</div>
<button type="reset">Reset</button>
<button>Submit</button>
</form>
</div>
)
}
export default HowReactWorks
edited for the people that don't know how to include HTML in react
You can use this method as well
const resetData = (e) => {
e.preventDefault();
settitle("");
setdate("");
};
<input type="text" onChange={(e) => settitle(e.target.value)} value={title} />
<input type="date" onChange={(e) => setdate(e.target.value)} value={date} />
<button onClick={resetData}>Reset Data</button>
This is the solution that worked for me, in the case of parent component triggering reset of child controlled input components:
const ParentComponent = () => {
const [reset, setReset] = useState()
const submitHandler = (e) => {
e.preventDefault()
//do your stuff
setReset(Date.now()) // pass some value to trigger update
}
return (
<form onSubmit={submitHandler}>
<ChildInputComponent reset={reset} />
<ChildInputComponent reset={reset} />
</form>
)
}
const ChildInputComponent = ({reset}) => {
const [value, setValue] = useState()
useEffect(() => {
setValue('')
}, [reset])
return <input value={value} onChange={(e) => setValue(e.target.value)} />
}
Assuming you declared
const [inputs, setInputs] = useState([]);
As multiple parameters. You can actually reset the items using this syntax:
setInputs([]);
Just in case, this how you define handleChange.
You can use this form or any ways you want.
const handleChange = (event) => {
const name = event.target.name;
const email = event.target.email;
const message = event.target.message;
const value = event.target.value;
setInputs(values => ({...values, [name]: value, [email]: value, [message]: value}))
}
You can use this form as an example.
<form onSubmit={handleSubmit}>
<div className="fields">
<div className="field half">
<label for="name">Name</label>
<input value={inputs.name || ''} type="text" name="name" id="nameId" onChange={handleChange} maxLength="30" />
</div>
<div className="field half">
<label for="email">Email</label>
<input value={inputs.email || ''} type="text" name="email" id="emailId" onChange={handleChange} maxLength="40"/>
</div>
<div className="field">
<label for="message">Message</label>
<textarea value={inputs.message || ''} name="message" id="messageId" rows="6" onChange={handleChange} maxLength="400" />
</div>
</div>
<ul className="actions">
<li><input type="submit" value="Send Message" className="primary" /></li>
<li><input onClick={resetDetails} type="reset" value="Clear" /></li>
</ul>
</form>
This is just one of many ways to declare forms. Good luck!
const onReset = () => {
form.resetFields();
};
state={
name:"",
email:""
}
handalSubmit = () => {
after api call
let resetFrom = {}
fetch('url')
.then(function(response) {
if(response.success){
resetFrom{
name:"",
email:""
}
}
})
this.setState({...resetFrom})
}
Why not use HTML-controlled items such as <input type="reset">

Get form data in React

I have a simple form in my render function, like so:
render : function() {
return (
<form>
<input type="text" name="email" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<button type="button" onClick={this.handleLogin}>Login</button>
</form>
);
},
handleLogin: function() {
// How can I access email and password here?
}
What should I write in my handleLogin: function() { ... } to access Email and Password fields?
There are a few ways to do this:
1) Get values from array of form elements by index
handleSubmit = (event) => {
event.preventDefault();
console.log(event.target[0].value)
}
2) Using name attribute in html
handleSubmit = (event) => {
event.preventDefault();
console.log(event.target.elements.username.value) // from elements property
console.log(event.target.username.value) // or directly
}
<input type="text" name="username"/>
3) Using refs
handleSubmit = (event) => {
console.log(this.inputNode.value)
}
<input type="text" name="username" ref={node => (this.inputNode = node)}/>
Full example
class NameForm extends React.Component {
handleSubmit = (event) => {
event.preventDefault()
console.log(event.target[0].value)
console.log(event.target.elements.username.value)
console.log(event.target.username.value)
console.log(this.inputNode.value)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input
type="text"
name="username"
ref={node => (this.inputNode = node)}
/>
</label>
<button type="submit">Submit</button>
</form>
)
}
}
Use the change events on the inputs to update the component's state and access it in handleLogin:
handleEmailChange: function(e) {
this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
this.setState({password: e.target.value});
},
render : function() {
return (
<form>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange}/>
<button type="button" onClick={this.handleLogin}>Login</button>
</form>);
},
handleLogin: function() {
console.log("EMail: " + this.state.email);
console.log("Password: " + this.state.password);
}
Working fiddle.
Also, read the docs, there is a whole section dedicated to form handling: Forms
Previously you could also use React's two-way databinding helper mixin to achieve the same thing, but now it's deprecated in favor of setting the value and change handler (as above):
var ExampleForm = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {email: '', password: ''};
},
handleLogin: function() {
console.log("EMail: " + this.state.email);
console.log("Password: " + this.state.password);
},
render: function() {
return (
<form>
<input type="text" valueLink={this.linkState('email')} />
<input type="password" valueLink={this.linkState('password')} />
<button type="button" onClick={this.handleLogin}>Login</button>
</form>
);
}
});
Documentation is here: Two-way Binding Helpers.
Adding on to Michael Schock's answer:
class MyForm extends React.Component {
constructor() {
super();
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
const data = new FormData(event.target);
console.log(data.get('email')); // Reference by form input's `name` tag
fetch('/api/form-submit-url', {
method: 'POST',
body: data,
});
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label htmlFor="username">Enter username</label>
<input id="username" name="username" type="text" />
<label htmlFor="email">Enter your email</label>
<input id="email" name="email" type="email" />
<label htmlFor="birthdate">Enter your birth date</label>
<input id="birthdate" name="birthdate" type="text" />
<button>Send data!</button>
</form>
);
}
}
See this Medium article: How to Handle Forms with Just React
This method gets form data only when the Submit button is pressed. It is much cleaner, IMO!
For those who don't want to use ref and reset the state with OnChange event, you can just use simple OnSubmit handle and loop through the FormData object.
Note that you cannot access formData.entries() directly since it is an iterable, you have to loop over it.
This example is using React Hooks:
const LoginPage = () => {
const handleSubmit = (event) => {
const formData = new FormData(event.currentTarget);
event.preventDefault();
for (let [key, value] of formData.entries()) {
console.log(key, value);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="text" name="username" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
</div>
);
};
And if you're using TypeScript:
export const LoginPage: React.FC<{}> = () => {
const handleSubmit: React.FormEventHandler<HTMLFormElement> = (event) => {
const formData = new FormData(event.currentTarget);
event.preventDefault();
for (let [key, value] of formData.entries()) {
console.log(key, value);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="text" name="username" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
</div>
);
};
An alternative approach is to use the ref attribute and reference the values with this.refs. Here is a simple example:
render: function() {
return (<form onSubmit={this.submitForm}>
<input ref="theInput" />
</form>);
},
submitForm: function(e) {
e.preventDefault();
alert(React.findDOMNode(this.refs.theInput).value);
}
More info can be found in the React docs:
https://facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute
For a lot of the reasons described in How do I use radio buttons in React? this approach isn't always the best, but it does present a useful alternative in some simple cases.
There isn't any need to use refs. You can access it using an event:
function handleSubmit(e) {
e.preventDefault()
const {username, password } = e.target.elements
console.log({username: username.value, password: password.value })
}
<form onSubmit={handleSubmit}>
<input type="text" id="username"/>
<input type="text" id="password"/>
<input type="submit" value="Login" />
</form>
An easy way to deal with refs:
class UserInfo extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const formData = {};
for (const field in this.refs) {
formData[field] = this.refs[field].value;
}
console.log('-->', formData);
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input ref="phone" className="phone" type='tel' name="phone"/>
<input ref="email" className="email" type='tel' name="email"/>
<input type="submit" value="Submit"/>
</form>
</div>
);
}
}
export default UserInfo;
You could switch the onClick event handler on the button to an onSubmit handler on the form:
render : function() {
return (
<form onSubmit={this.handleLogin}>
<input type="text" name="email" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
);
},
Then you can make use of FormData to parse the form (and construct a JSON object from its entries if you want).
handleLogin: function(e) {
const formData = new FormData(e.target)
const user = {}
e.preventDefault()
for (let entry of formData.entries()) {
user[entry[0]] = entry[1]
}
// Do what you will with the user object here
}
If all your inputs / textarea have a name, then you can filter all from event.target:
onSubmit(event){
const fields = Array.prototype.slice.call(event.target)
.filter(el => el.name)
.reduce((form, el) => ({
...form,
[el.name]: el.value,
}), {})
}
Totally uncontrolled form 😊 without onChange methods, value, defaultValue...
I would suggest the following approach:
import {Autobind} from 'es-decorators';
export class Form extends Component {
#Autobind
handleChange(e) {
this.setState({[e.target.name]: e.target.value});
}
#Autobind
add(e) {
e.preventDefault();
this.collection.add(this.state);
this.refs.form.reset();
}
shouldComponentUpdate() {
return false;
}
render() {
return (
<form onSubmit={this.add} ref="form">
<input type="text" name="desination" onChange={this.handleChange}/>
<input type="date" name="startDate" onChange={this.handleChange}/>
<input type="date" name="endDate" onChange={this.handleChange}/>
<textarea name="description" onChange={this.handleChange}/>
<button type="submit">Add</button>
</form>
)
}
}
Here is the shortest way to get data from the form and the best way to avoid id and ref just by using FormData:
import React, { Component } from 'react'
class FormComponent extends Component {
formSubmit = (event) => {
event.preventDefault()
var data = new FormData(event.target)
let formObject = Object.fromEntries(data.entries())
console.log(formObject)
}
render() {
return (
<div>
<form onSubmit={this.formSubmit}>
<label>Name</label>
<input name="name" placeholder="name" />
<label>Email</label>
<input type="email" name="email" />
<input type="submit" />
</form>
</div>
)
}
}
export default FormComponent
More clear example with es6 destructing
class Form extends Component {
constructor(props) {
super(props);
this.state = {
login: null,
password: null,
email: null
}
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value
})
}
onSubmit(e) {
e.preventDefault();
let login = this.state.login;
let password = this.state.password;
// etc
}
render() {
return (
<form onSubmit={this.onSubmit.bind(this)}>
<input type="text" name="login" onChange={this.onChange.bind(this)} />
<input type="password" name="password" onChange={this.onChange.bind(this)} />
<input type="email" name="email" onChange={this.onChange.bind(this)} />
<button type="submit">Sign Up</button>
</form>
);
}
}
Give your inputs ref like this
<input type="text" name="email" placeholder="Email" ref="email" />
<input type="password" name="password" placeholder="Password" ref="password" />
Then you can access it in your handleLogin like so:
handleLogin: function(e) {
e.preventDefault();
console.log(this.refs.email.value)
console.log(this.refs.password.value)
}
I use like this using React Component state:
<input type="text" name='value' value={this.state.value} onChange={(e) => this.handleChange(e)} />
handleChange(e){
this.setState({[e.target.name]: e.target.value})
}`
Also, this can be used too.
handleChange: function(state,e) {
this.setState({[state]: e.target.value});
},
render : function() {
return (
<form>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleChange.bind(this, 'email')} />
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handleChange.bind(this, 'password')}/>
<button type="button" onClick={this.handleLogin}>Login</button>
</form>
);
},
handleLogin: function() {
console.log("EMail: ", this.state.email);
console.log("Password: ", this.state.password);
}
If you are using Redux in your project, you can consider using the higher order component redux-form.
In many events in JavaScript, we have event which gives an object, including what event happened and what are the values, etc.
That's what we use with forms in React as well.
So in your code you set the state to the new value. Something like this:
class UserInfo extends React.Component {
constructor(props) {
super(props);
this.handleLogin = this.handleLogin.bind(this);
}
handleLogin(e) {
e.preventDefault();
for (const field in this.refs) {
this.setState({this.refs[field]: this.refs[field].value});
}
}
render() {
return (
<div>
<form onSubmit={this.handleLogin}>
<input ref="email" type="text" name="email" placeholder="Email" />
<input ref="password" type="password" name="password" placeholder="Password" />
<button type="button">Login</button>
</form>
</div>
);
}
}
export default UserInfo;
Also this is the form example in React v.16, just as reference for the form you creating in the future:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
onChange(event){
console.log(event.target.value);
}
handleSubmit(event){
event.preventDefault();
const formData = {};
for (const data in this.refs) {
formData[data] = this.refs[data].value;
}
console.log(formData);
}
<form onSubmit={this.handleSubmit.bind(this)}>
<input type="text" ref="username" onChange={this.onChange} className="form-control"/>
<input type="text" ref="password" onChange={this.onChange} className="form-control"/>
<button type="submit" className="btn-danger btn-sm">Search</button>
</form>
Output image attached here
To improve the user experience; when the user clicks on the submit button, you can try to get the form to first show a sending message. Once we've received a response from the server, it can update the message accordingly. We achieve this in React by chaining statuses. See codepen or snippets below:
The following method makes the first state change:
handleSubmit(e) {
e.preventDefault();
this.setState({ message: 'Sending...' }, this.sendFormData);
}
As soon as React shows the above Sending message on screen, it will call the method that will send the form data to the server: this.sendFormData(). For simplicity I've added a setTimeout to mimic this.
sendFormData() {
var formData = {
Title: this.refs.Title.value,
Author: this.refs.Author.value,
Genre: this.refs.Genre.value,
YearReleased: this.refs.YearReleased.value};
setTimeout(() => {
console.log(formData);
this.setState({ message: 'data sent!' });
}, 3000);
}
In React, the method this.setState() renders a component with new properties. So you can also add some logic in render() method of the form component that will behave differently depending on the type of response we get from the server. For instance:
render() {
if (this.state.responseType) {
var classString = 'alert alert-' + this.state.type;
var status = <div id="status" className={classString} ref="status">
{this.state.message}
</div>;
}
return ( ...
codepen
This might help Meteor (v1.3) users:
render: function() {
return (
<form onSubmit={this.submitForm.bind(this)}>
<input type="text" ref="email" placeholder="Email" />
<input type="password" ref="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
);
},
submitForm: function(e) {
e.preventDefault();
console.log( this.refs.email.value );
console.log( this.refs.password.value );
}
This is an example of dynamically added fields. Here form data will store by input name key using a React useState hook.
import React, { useState } from 'react'
function AuthForm({ firebase }) {
const [formData, setFormData] = useState({});
// On Form Submit
const onFormSubmit = (event) => {
event.preventDefault();
console.log('data', formData)
// Submit here
};
// get Data
const getData = (key) => {
return formData.hasOwnProperty(key) ? formData[key] : '';
};
// Set data
const setData = (key, value) => {
return setFormData({ ...formData, [key]: value });
};
console.log('firebase', firebase)
return (
<div className="wpcwv-authPage">
<form onSubmit={onFormSubmit} className="wpcwv-authForm">
<input name="name" type="text" className="wpcwv-input" placeholder="Your Name" value={getData('name')} onChange={(e) => setData('name', e.target.value)} />
<input name="email" type="email" className="wpcwv-input" placeholder="Your Email" value={getData('email')} onChange={(e) => setData('email', e.target.value)} />
<button type="submit" className="wpcwv-button wpcwv-buttonPrimary">Submit</button>
</form>
</div>
)
}
export default AuthForm
For TypeScript users
import react from 'react'
interface FormInterface {
[key: string]: string
}
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
let formData = new FormData(event.currentTarget)
let formObj: FormInterface = {}
for (let [key, value] of Array.from(formData.entries())) {
formObj[key] = value.toString()
}
};
<form onSubmit={handleSubmit}>
<input type="text" name="email" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
The simplest solution that came to my mind is this:
<form onSubmit={(e) => handleLogin(e)}>
<input type="text" name="email" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
Your handle fuction:
const handleLogin = (e) => {
e.preventDefault()
const data = {
email: e.target.elements.email.value,
password: e.target.elements.password.value
}
console.log('FormData: ', data)
}
When you click on your login button you will see FormData in console in this format:
FormData: {email: 'whatever you tiped here', password: 'also whatever you tiped here'}.
e.target.elements.email.value targets elements with specific name, in your case it is email and password.
After console.log in handleLogin, you can do some verification logic and login logic.
If you have multiple occurrences of an element name, then you have to use forEach().
HTML
<input type="checkbox" name="delete" id="flizzit" />
<input type="checkbox" name="delete" id="floo" />
<input type="checkbox" name="delete" id="flum" />
<input type="submit" value="Save" onClick={evt => saveAction(evt)}></input>
JavaScript
const submitAction = (evt) => {
evt.preventDefault();
const dels = evt.target.parentElement.delete;
const deleted = [];
dels.forEach((d) => { if (d.checked) deleted.push(d.id); });
window.alert(deleted.length);
};
Note the dels in this case is a RadioNodeList, not an array, and is not an Iterable. The forEach() is a built-in method of the list class. You will not be able to use a map() or reduce() here.
TypeScript will complain if you try Aliaksandr Sushkevich's solution. One workaround can be done using type assertions:
<form
onSubmit={(e: React.SyntheticEvent) => {
e.preventDefault();
const target = e.target as typeof e.target & {
username: { value: string };
password: { value: string };
};
const username = target.username.value; // typechecks
const password = target.password.value; // typechecks
// etc...
}}
>
<input type="text" name="username"/>
...
Though, this is still just a workaround, because here you are telling TypeScript what to expect. This will break at runtime if you add a value that doesn't have a corresponding input element.
I think this is also the answer that you need. In addition, Here I add the required attributes. onChange attributes of Each input components are functions. You need to add your own logic there.
handleEmailChange: function(e) {
this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
this.setState({password: e.target.value});
},
formSubmit : async function(e) {
e.preventDefault();
// Form submit Logic
},
render : function() {
return (
<form onSubmit={(e) => this.formSubmit(e)}>
<input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} required />
<input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} required />
<button type="button">Login</button>
</form>);
},
handleLogin: function() {
//Login Function
}
Here is my approach for collecting multiple form inputs using single inputChangeHandler
import React from "react";
const COLORS = ["red", "orange", "yellow", "purple", "green", "white", "black"];
export default function App() {
const initialFormFields = {
name: undefined,
email: undefined,
favourite_color: undefined
};
const [formInput, setFormInput] = React.useState(initialFormFields);
function inputChangeHandler(event) {
setFormInput(prevFormState => ({
...prevFormState,
[event.target.name]: event.target.value
}))
};
return (
<div className="App">
<form>
<label>Name: <input name="name" type="text" value={formInput.name} onChange={inputChangeHandler}/></label>
<label>Email: <input name="email" type="email" value={formInput.email} onChange={inputChangeHandler}/></label>
<div>
{COLORS.map(color => <label><input type="radio" name="favourite_color" value={color} key={color} onChange={inputChangeHandler}/> {color} </label>)}
</div>
</form>
<div>
Entered Name: {formInput.name}
Entered Email: {formInput.email}
Favourite Color: {formInput.favourite_color}
</div>
</div>
);
}
This will be the easiest method:
const formValidator = (form) => {
let returnData = {}
console.log(form.length);
for (let i = 0; i < form.length; i++) {
const data = form[i]
if (data.name != null && data.name != "") {
returnData[data.name] = data.value;
}
}
return returnData
}
In the form, simply use:
<form onSubmit={(e) => {
e.preventDefault()
let data = formValidator(e.currentTarget)
}}>
<RoundTextFiled name='app-id' style={{ marginTop: '10px', borderRadius: '20px' }} label="App id" fullWidth required />
<RoundTextFiled name='api-hash' style={{ marginTop: '5px' }} label="Api hash" fullWidth required />
<RoundTextFiled name='channel-id' style={{ marginTop: '5px' }} label="Channel id" fullWidth required />
<Button type='submit' variant="contained" fullWidth style={{ padding: '10px', marginTop: '5px', borderRadius: '10px' }}>Login</Button>
</form>
<form onSubmit={handleLogin}>
<input type="text" name="email" placeholder="Email" />
<input type="text" name="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
const handleLogin = (event) => {
event.preventDefault();
console.log(event.target[0].value)
console.log(event.target[1].value)
}
Use:
import { useState } from 'react'
export default function App() {
const [data, setData] = useState({})
const updateData = e => {
setData({
...data,
[e.target.name]: e.target.value
})
}
const submit = e => {
e.preventDefault()
console.log(data)
}
return (
<form onSubmit={submit}>
<input
name="email"
type="email"
onChange={updateData}
/>
<input
name="password"
type="password"
onChange={updateData}
/>
<button>Submit</button>
</form>
)
}

Resources