95

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('');

Chris
  • 53,920
  • 18
  • 108
  • 124
ChemseddineZ
  • 1,548
  • 2
  • 12
  • 24

17 Answers17

139

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>
Community
  • 1
  • 1
Chris
  • 53,920
  • 18
  • 108
  • 124
  • 1
    thanks for your answer, i'm using uncontrolled fileds so i user reset() function, it's working like a charm now – ChemseddineZ May 11 '17 at 18:17
  • 3
    For future readers wondering what 'controlled' vs 'uncontrolled fields are, check out the [docs on the React homepage for working with forms](https://facebook.github.io/react/docs/forms.html). – Dan Esparza May 11 '17 at 18:20
  • @Chris what's the best practice for clearing a form using controlled components? I was told "Setting state of an input to '' is considered an anti-pattern.", they suggested using this on componentWillUnmount but with caution. And as an alternative to use document.getElementById("someID").value = '' so I got lost ? any ideas – yokodev Oct 21 '17 at 06:24
  • @yokodev, not quite following. Please consider posting a new question and post more info there. Also state that you've read this question but that you still don't understand X and Y. Also ping me with a link to it and I'll check it out. – Chris Oct 23 '17 at 11:22
  • I think that clearing the form with a ref and the reset() method (second option) is the most convenient and performant, unless you need controlled fields (third option). – Àlex Garcés Jul 22 '18 at 12:35
  • 1
    how to do this with hooks ? – Usman Iqbal Jul 19 '20 at 20:45
  • @UsmanI almost the same way. Just remove `this` from `this.handleInput` and make `cancelCourse` a constant – Chris Jul 19 '20 at 21:36
86

Very easy:

handleSubmit(e){
    e.preventDefault();
    e.target.reset();
}
<form onSubmit={this.handleSubmit.bind(this)}>
  ...
</form>

Good luck :)

18

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
Andrea
  • 483
  • 8
  • 10
  • +1 for your use of `initialState`, great if you're resetting a form in several places (a reset button but also after submitting, for example) – Robin Métral Apr 18 '19 at 11:10
8

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>
IcedMonk
  • 99
  • 1
  • 8
3

The HTMLFormElement.reset() method restores a form element's default values. This method does the same thing as clicking the form's reset button.

import React from 'react'


export default class Example extends React.Component {

  /*
  // One way
  handleSubmitted = ({ res, fields, form }) => {
    form.reset() // resets "username" field to "admin"
  }
*/
// Another way
 handleSubmitted = (e) => {
    e.target.reset() // resets "username" field to "admin"
  }

  render() {
    return (
      <form onSubmitted={this.handleSubmitted}>
        <input
          name="username"
          initialValue="admin" />
      </form>
    )
  }
}
MD SHAYON
  • 7,911
  • 47
  • 35
2

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>
    }
}
Sharad Pawar
  • 251
  • 1
  • 2
  • 16
  • 1
    Correct, but I've already covered this in my answer. Also, using string literals for `refs` is deprecated. https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs – Chris Oct 20 '17 at 07:59
  • @Chris, yeah that true as `refs` difficult to test especially when using `shallow` – Januartha Aug 10 '18 at 15:39
1

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})
      } 
Webwoman
  • 8,096
  • 11
  • 34
  • 78
1

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>
    )
  }
}
Nimish goel
  • 2,357
  • 4
  • 24
  • 39
1

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>
      </>
    )
  }
thiago89
  • 103
  • 1
  • 5
0

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.

Michael
  • 93
  • 1
  • 4
0

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>
    )
  }
}
bello hargbola
  • 359
  • 5
  • 8
0

/* 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;
    
Awsaf
  • 21
  • 5
0

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
Sir XtC
  • 81
  • 6
  • Please try to answer the questions as they are asked, giving answers that won’t help in the given situation isn’t helpful. The question clearly shows they are already using React, so giving an answer that won’t work in a React world isn’t a viable solution. – Brook Jordan Jun 13 '21 at 12:48
0

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>
0

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)} />
}

Radi Totev
  • 81
  • 6
-1
state={ 
  name:"",
  email:""
}

handalSubmit = () => {
  after api call 
  let resetFrom = {}
  fetch('url')
  .then(function(response) {
    if(response.success){
       resetFrom{
          name:"",
          email:""
      }
    }
  })
  this.setState({...resetFrom})
}
  • If possible, it's better to include some explanation along with your code, to describe how this answers the question, and why it's different from the several other answers already here. – DaveyDaveDave Nov 02 '18 at 10:29
-2

Why not use HTML-controlled items such as <input type="reset">

Erikm
  • 57
  • 4