最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React - How to reset input field(controlled) to default value - Stack Overflow

programmeradmin0浏览0评论

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;

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;
Share Improve this question edited Mar 20, 2020 at 20:50 babybear asked Mar 20, 2020 at 20:43 babybearbabybear 8442 gold badges11 silver badges25 bronze badges 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. – Brian Thompson Commented Mar 20, 2020 at 20:52
  • Also is there a reason why you use onBlur instead of just using onChange? – Brian Thompson 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 – Devon Norris 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. – babybear 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/docs/two-way-binding-helpers.html – Devon Norris Commented Mar 20, 2020 at 21:10
 |  Show 1 more ment

2 Answers 2

Reset to default 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./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />

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
}
发布评论

评论列表(0)

  1. 暂无评论