1

I have input whose value is changed by button element. I need a way to call onChange of that input. I have some validation that has to be done when the value is changed.

I found some answers on StackOverflow but they are using dispatch which they didn't explain properly or I didn't use it properly.

But onChange is not called when the state is updated. Here is what I have by now

<div className="input-group">
  <input type="text" className="form-control quantity-field text-center" onChange={(e) => this.handleChange(e)} value={this.state.quantity}/>
  <button onClick={(e) => this.handleIncDec(e)}>+</button>
</div>
  handleIncDec = (e) => {
    e.preventDefault()

    this.setState({
      quantity: this.state.quantity += 1
    })
  }

handleChange = e => {
    console.log(e.target.value);

    const re = /^[0-9\b]+$/;
    if (e.target.value === '' || re.test(e.target.value)) {
      this.setState({
        quantity: e.target.value
      })
    }
  };

The value of the input is updated correctly as it should be but onChange is never called unless I updated value directly in that input and not with button, which is not what I want.

If you need any other info to tell me and I will provide it.

3
  • Try this: stackoverflow.com/questions/42550341/… Commented Nov 21, 2019 at 23:07
  • Try quantity: this.state.quantity + 1 instead so you won't mutate state \and if you have an input that is a number try <input type="number" instead. Commented Nov 21, 2019 at 23:10
  • @zixuan no it is not working. I tried that one HMR read question again. Value is updated properly which mean setState is working as it should. onChange is never triggered. Commented Nov 21, 2019 at 23:14

1 Answer 1

2

The onChange-event will by default only be called on userinputs. Most of the time you can avoid trigger the onChange event programatically by using lifecycles-methods like ComponentDidUpdate or similar in React. In your example it looks to me like you only need to validte input from two different sources, so I would suggest an easier implementation.

Can you create a validationfunction instead that you can use on both handleChange and handleInDec?

You should also avoid updating state based on previous state with this.setState({ quantity: this.state.quantity += 1}), as you are not guaranteed that state always will be updated (Remember, setState is asynchronous). Instead use a the return value from setState that guarantees updated state-values

class Test extends React.Component {
  constructor() {
    super();

    this.state = {
      quantity: 0
    };
  }

  handleIncDec = e => {
    e.preventDefault();

    this.setState(prevState => {
      var newQuantity = prevState.quantity + 1;
      if (this.isValidInputData(newQuantity)) {
        return {
          quantity: newQuantity
        };
      }
    });
  };

  handleChange = e => {
    if (this.isValidInputData(e.target.value)) {
      this.setState({
        quantity: e.target.value
      });
    }
  };

  isValidInputData = newQuantity => {
    const re = /^[0-9\b]+$/;
    return newQuantity === "" || re.test(newQuantity);
  };

  render() {
    return (
      <div className="input-group">
        <input
          type="text"
          className="form-control quantity-field text-center"
          onChange={this.handleChange}
          value={this.state.quantity}
        />
        <button onClick={this.handleIncDec}>+</button>
      </div>
    );
  }
}

ReactDOM.render(<Test />, 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"></div>

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

1 Comment

Is there anything else I can help you with to figure out this @mileta-dulovic?

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.