1

I want to restore the default values on all input fields and total on the click of button 'Restore Default', but it is not working. In the code I have so far, all the elements are wrapped within a grid.

The SO questions I referred to talk about:

  1. Wrapping all elements in a form or a div and call reset()
  2. Use e.target.reset() on the event. I tried this with onClick event of button, but says that reset is not a function.

What is the preferred way to implement this functionality? Thanks in advance!

class Test extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
    code1: this.props.defaults[0],
    code2: this.props.defaults[1],
    code3: this.props.defaults[2],
    total : 0
  };
  this.handleInput = this.handleInput.bind(this);
  this.restoreDefaults = this.restoreDefaults(this);
 }

handleInput() {
  //some logic
}

updateCode = (e, k) => {
    this.setState({
        [`code${k}`]: e.target.value
      },
      () => {
        this.updateTotal();
      });
  }

  updateTotal = () => {
    this.setState(prevState => ({
        total: (+prevState.code1 + +prevState.code2 + +prevState.code3),
      }),
      () => {
        if (this.state.total !== 100) {
          this.setState({
            isTotalInvalid: true
          });
        } else {
          this.setState({
            isTotalInvalid: false
          });
        }
      });
  }

  restoreDefaults() {
    this.setState({
      code1: this.props.defaults[0],
      code2: this.props.defaults[1],
      code3: this.props.defaults[2],
      total: 0,
    )};
  }

  render() {
    return (
    <Spacer>
     <Grid>
      <Grid.Row>
       <Grid.Column tiny={12} medium={10}>
          <input type="number" defaultValue={this.state.code1} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 1)} />
       </Grid.Column>
       <Grid.Column tiny={12} medium={10}>
          <input type="number" defaultValue={this.state.code2} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 2)} />
       </Grid.Column>
       <Grid.Column tiny={12} medium={10}>
          <input type="number" defaultValue={this.state.code3} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 3)} />
          Total Field:

          <span fontSize={14} weight={700}>{this.state.total}</span>
         </Grid.Column>
        </Grid.Row>
        <Grid.Row>
          <Button text="Restore Default" type="button" onClick= 
            {this.restoreDefaults} />
        </Grid.Row>
       </Grid>
      </Spacer>
       );
    }
  }

export default Test;
6
  • In the question you say "controlled", but these are uncontrolled. You do not assign them a value. For controlled inputs, you would just reset their values in state. Commented Mar 20, 2020 at 20:52
  • Also is there a reason why you use onBlur instead of just using onChange? Commented Mar 20, 2020 at 20:53
  • It doesn't appear that you are doing 2-way data binding. You should have a value attribute on your input as well that should be controlled by your state Commented Mar 20, 2020 at 20:55
  • 1
    @DevonNorris Now that you mention value attribute, I feel that's where I'm going wrong. I'm updating states on events but not tying states to input values. Commented Mar 20, 2020 at 21:03
  • 1
    @Vidhi yep, try binding the values to your state and see what happens. Also here is a short article from the react docs: reactjs.org/docs/two-way-binding-helpers.html Commented Mar 20, 2020 at 21:10

2 Answers 2

5

A controlled input requires two parts.

  • A value provided to the input
  • A change handler

Remember: defaultValue only sets the input's value once. After that it has no effect.

This allows you to control the value of the inputs programatically.

I've added a very simplified example below.

In this example we control the values by keeping them in state. But this could be in props or redux or wherever.

Then when we want to reset the form, we just need to change the state back to its initial values. Since the input is informed through the value prop (our state) it effectively resets.

class Example extends React.Component {
  state = {
    code1: '',
    code2: '',
    code3: '',
  }
  
  handleChange = (e) => {
    this.setState({ [e.target.name]: e.target.value });
  }
  
  handleReset = () => {
    this.setState({
      code1: '',
      code2: '',
      code3: '',
    });
  }

  render() {
    return (
      <div>
        <div>
          <input 
            type="number" 
            name="code1"
            value={this.state.code1} 
            onChange={this.handleChange} 
            min="0" 
            max="100" 
          />
        </div>
        <div>
          <input 
            type="number" 
            name="code2"
            value={this.state.code2} 
            onChange={this.handleChange} 
            min="0" 
            max="100" 
          />
        </div>
        <div>
          <input 
            type="number" 
            name="code3"
            value={this.state.code3} 
            onChange={this.handleChange} 
            min="0" 
            max="100" 
          />
        </div>
        <button onClick={this.handleReset}>Reset</button>
      </div>
    )
  }
}

ReactDOM.render(<Example/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />

Sign up to request clarification or add additional context in comments.

Comments

0

To reset all the inputs with the click of a button:

  1. Put all the inputs in a <form>
  2. Instead of <button>, use input reset <input type="reset" />
  3. Instead of value, set default value <input defaultValue={myDefaultValue} />
  4. The input reset must be within <form>

By implementing those changes, render() would look like this:

render() {
  return (
    <form>
      <Spacer>
        <Grid>
          <Grid.Row>
            <Grid.Column tiny={12} medium={10}>
              <input 
                type="number" 
                defaultValue={this.state.code1} 
                min="0" 
                max="100" 
                onKeyPress={this.handleInput} 
                onBlur={e => this.updateCode(e, 1)} />
            </Grid.Column>
            <Grid.Column tiny={12} medium={10}>
              <input 
                type="number" 
                defaultValue={this.state.code2} 
                min="0" 
                max="100" 
                onKeyPress={this.handleInput} 
                onBlur={e => this.updateCode(e, 2)} />
            </Grid.Column>
            <Grid.Column tiny={12} medium={10}>
              <input 
                type="number" 
                defaultValue={this.state.code3} 
                min="0" 
                max="100" 
                onKeyPress={this.handleInput} 
                onBlur={e => this.updateCode(e, 3)} />
              Total Field:
              <span fontSize={14} weight={700}>
                {this.state.total}
              </span>
            </Grid.Column>
          </Grid.Row>
          <Grid.Row>
            <input 
              value="Restore Default" 
              type="reset" />
          </Grid.Row>
        </Grid>
      </Spacer>
    </form>
  );
}

The <form> element has a reset() function that is AUTOMATICALLY called when the input reset button is clicked.

NOTE: If you add onClick to the input reset button, the <form> will not reset. In this case, you must manually call reset(). So if you use onClick like this:

<input type="reset" value="Restore Default" onClick={handleClick} />

You should manually reset the <form> like this:

function handleClick(event) {
  const form = event.currentTarget.form;
  form.reset();
  //YOUR CUSTOM CODE GOES HERE
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.