Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling multiple onChange callbacks in a React component

Tags:

reactjs

This is how I'm currently handling the scenario with two input boxes. As a separate update method for each one. Can/should this be done with a single handleChange method instead?

https://codepen.io/r11na/pen/bZKOpj?editors=0011

class App extends React.Component {
  constructor(props) {
    super(props);

    this.handleChange1 = this.handleChange1.bind(this);
    this.handleChange2 = this.handleChange2.bind(this);

    this.state = {
      name1: '',
      name2: ''
    };
  };

  handleChange1(e) {
    this.setState({
      name1: e.target.value
    });
  };

  handleChange2(e) {
    this.setState({
      name2: e.target.value
    });
  };

  render() {
    return (
      <div class="row column">
        <Label name={this.state.name1}/>
        <Input onChange={this.handleChange1} />
        <Label name={this.state.name2}/>
        <Input onChange={this.handleChange2} />
      </div>
    );
  };
}

const Label = props => (
  <p {...props}>Hello: <span className="label-name">{props.name}</span></p>
);

const Input = props => (
  <input placeholder="Enter your name" {...props} type="text" /> 
);

ReactDOM.render(<App />, document.getElementById('app'))
like image 744
Riina Avatar asked Dec 14 '22 04:12

Riina


1 Answers

Can/should this be done with a single handleChange method instead?

You can simplify your code like so.

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      name1: '',
      name2: ''
    };
  };

  handleChange(e, name) {
    this.setState({ [name]: e.target.value });
  };

  render() {
    return (
      <div class="row column">
        <Label name={this.state.name1}/>
        <Input onChange={ (e) => this.handleChange(e, 'name1') } />
        <Label name={this.state.name2}/>
        <Input onChange={ (e) => this.handleChange(e, 'name2')  } />
      </div>
    );
  };
}

Example


Thanks @Alik that mentioned about eslint rule jsx-no-bind,

A bind call or arrow function in a JSX prop will create a brand new function on every single render. This is bad for performance, as it will result in the garbage collector being invoked way more than is necessary.

Following this rule you can change your code like

class App extends React.Component {
  constructor(props) {
    super(props);

    this.onChange = {
      name1: this.handleChange.bind(this, 'name1'),
      name2: this.handleChange.bind(this, 'name2'),
    }

    this.state = {
      name1: '',
      name2: ''
    };
  };

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


  render() {
    return (
      <div class="row column">
        <Label name={this.state.name1}/>
        <Input onChange={ this.onChange.name1 } />
        <Label name={this.state.name2}/>
        <Input onChange={ this.onChange.name2 } />
      </div>
    );
  };
}

Example

like image 62
Oleksandr T. Avatar answered Jan 11 '23 11:01

Oleksandr T.