how to Creating a single input handler

Viewed 300

I have several inputs ,Each of the inputs has its own value .How can I have a function for (onChange) all of them ? For example

 handleChange1(event) {
    this.setState({value1: event.target.value});
  }
 handleChange2(event) {
    this.setState({value2: event.target.value});
  }
  }
 handleChange3(event) {
    this.setState({value3: event.target.value});
  }

  <input type="text" value={this.state.value1} onChange={this.handleChange1} />
  <input type="text" value={this.state.value2} onChange={this.handleChange2} />
  <input type="text" value={this.state.value3} onChange={this.handleChange3} />

I just want to have one handleChange

6 Answers

When you need to handle multiple controlled input elements, you can add a name attribute to each element and let the handler function choose what to do based on the value of event.target.name.

For example:

handleInputChange(event) {
  const target = event.target;
  const value = target.type === 'checkbox' ? target.checked : target.value;
  const name = target.name;

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

render() {
return (
  <form>
    <label>
      value1:
      <input
        name="value1"
        type="checkbox"
        checked={this.state.value1}
        onChange={this.handleInputChange} />
    </label>
    <br />
    <label>
      value2:
      <input
        name="value2"
        type="number"
        value={this.state.value2}
        onChange={this.handleInputChange} />
    </label>
    <br />
    <label>
      value3:
      <input
        name="value3"
        type="text"
        value={this.state.value3}
        onChange={this.handleInputChange} />
    </label>
  </form>
 );
}
}

You can simply do by using input name:

Code:

import React from "react";
import "./styles.css";

class MyComponent extends React.Component {
  state = {
    value1: "",
    value2: "",
    value3: ""
  };
  handleChange = (event) => {
    this.setState({ [event.target.name]: event.target.value });
  };
  render() {
    console.log(this.state);
    return (
      <>
        <input
          name="value1"
          value={this.state.value1}
          type="text"
          value={this.state.value1}
          onChange={this.handleChange}
        />
        <input
          name="value2"
          value={this.state.value2}
          type="text"
          value={this.state.value2}
          onChange={this.handleChange}
        />
        <input
          name="value3"
          value={this.state.value3}
          type="text"
          value={this.state.value3}
          onChange={this.handleChange}
        />
      </>
    );
  }
}

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <MyComponent />
    </div>
  );
}


Demo: https://codesandbox.io/s/beautiful-brook-p46zs?file=/src/App.js:0-1092

If you add a name to the input you can use that off of the event.

handleChange1(event) {
    const {name, value} = event.target
    this.setState({[name]: value});
}

<input name="inputone" type="text" value={this.state.value1} onChange={this.handleChange1} />
<input name="inputtwo" type="text" value={this.state.value2} onChange={this.handleChange2} />
<input name="inputthree" type="text" value={this.state.value3} onChange={this.handleChange3} />

i always do this by switch case

 handleChange(event) {
            switch (event.target.name) {
                case 'name1':
                    this.setState({ name1: event.target.value });
                    break;
                case 'name2':
                    this.setState({ name2: event.target.value });
                    break;
                 case 'name3':
                    this.setState({ name3: event.target.value });
                    break;
                default:
                    break;
            }
    }


<input type="text" name="name1" value={this.state.value1} onChange={this.handleChange1} />
  <input type="text" name="name2" value={this.state.value2} onChange={this.handleChange2} />
  <input type="text" name="name3" value={this.state.value3} onChange={this.handleChange3} />

You can use react hooks useState for each field:

const [value1,setvalue1] = useState();
<input type="text" value={value1} onChange={(e)=>setvalue1(e.target.value)}/>

You still do have handle change to each input but you write less code.

You can also look here for more info about react hooks: https://reactjs.org/docs/hooks-state.html

If all inputs are same, I think we can render them dynamically so we don't need to repeat ourself and also make the code more clean. I think we can have an array of inputs then render dynamically. By using closure, we can have one handleChange function for all inputs.

state={
  inputValues: []
}
handleChange(index){
  return (event)=>{
    this.state.inputValues[index] = event.target.value;
    this.setState({inputValues: this.state.inputValues})
  }
  
}

render(){
  return this.states.inputValues.map((inputValue, index)=>
    <input type="text" value={inputValue} onChange={this.handleChange(index)} />    
  )
}
Related