user1283776
user1283776

Reputation: 21764

React OnInputChange handler with various input types with TypeScript?

I have multiple input fields:

<label>
    <span className="codes__input-label">Count</span>
    <input
        type="number"
        value={this.state.count}
        onChange={this.onInputChange}
    />
</label>

<label>
    <span className="codes__input-label">One time Usage</span>
    <input
        type="text"
        value={this.state.distributor}
        onChange={this.onInputChange}
    />
</label>

<label>
    <span className="codes__input-label">One time Usage</span>
    <input
        type="checkbox"
        value={this.state.oneTimeUsage}
        onChange={this.onInputChange}
    />
</label>

It seems repetitive to have one handler for each event, so I want to have one handler for all of them.

What is a good approach?

Here is my best attempt. I get a long TypeScript errors on the setState lines.

onInputChange(event: React.FormEvent<HTMLInputElement>): void {
    switch (event.currentTarget.type) {
        case "number":
            this.setState({[event.currentTarget.name]: event.currentTarget.valueAsNumber});
        break; 
        case "text":
            this.setState({[event.currentTarget.name]: event.currentTarget.value});
        break; 
        case "checkbox":
            this.setState({[event.currentTarget.name]: event.currentTarget.checked});
        break; 
    }
}

Upvotes: 1

Views: 1389

Answers (1)

devserkan
devserkan

Reputation: 17608

FYI, I don't know Typescript but your problem is not related to this. First thing I see, you don't have name attributes for your input's. So, add them. The second problem is you don't have a checked value for the checkbox, add it, too.

If you haven't already bound onInputChange method, bind it. Then it should work as expected.

<label>
  <span className="codes__input-label">Count</span>
  <input
    name="count"
    type="number"
    value={this.state.count}
    onChange={this.onInputChange}
  />
</label>

<label>
  <span className="codes__input-label">One time Usage</span>
  <input
    name="distributor"
    type="text"
    value={this.state.distributor}
    onChange={this.onInputChange}
  />
</label>

<label>
  <span className="codes__input-label">One time Usage</span>
  <input
    name="oneTimeUsage"
    type="checkbox"
    checked={this.state.oneTimeUsage}
    onChange={this.onInputChange}
  />
</label>

Though, if you don't need valueAsNumber directly and can use the value itself then do some number manipulation, there is a nicer method generally people use for this method.

onInputChange = (e) => {
  const { target, target: { name } } = e;
  const value = target.type === 'checkbox' ? target.checked : target.value;

  this.setState({
        [name]: value
 });
}

Upvotes: 2

Related Questions