Search code examples
reactjsevent-handlingreact-state-management

React - use single event handler to set state for multiple inputs?


I'm new to React and wondering if it's possible to use a single event handler to set the state for many inputs. Namely, I'm not sure how to get the state "key" from the input into the handler, if that makes sense.

import React from 'react';

class User extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
    this.state = {
      id: props.id,
      firstName: props.firstName,
      lastName: props.lastName,
      email: props.email,
    };
  }

  // how do I (can I) use this single handler to independently change the state of multiple inputs?
  handleChange(e) {
    this.setState({ this.state.key // wrong!: this.inputRef.current.value });
  }

  render() {
    return (
      <div>
        <input type="text" ref={this.inputRef} id={`first_${this.state.id}`} value={this.state.firstName} onChange={this.handleChange.bind(this)} />
        <input type="text" ref={this.inputRef} id={`last_${this.state.id}`} value={this.state.lastName} onChange={this.handleChange.bind(this)} />
        <input type="email" ref={this.inputRef} id={`email_${this.state.id}`} value={this.state.email} onChange={this.handleChange.bind(this)} />
        // imagine ten more inputs
      </div>
    )
  }
}

Solution

  • What you're trying to do is more related to JS events handling.

    handleChange(event) {
          const {name, value} = event.target;
    
          this.setState({
              [name]: value
          });
        }
    
    • event.target is the element that fired that event (button, text area, etc..) and you can grab whatever attribute you want from it (name, type, value, etc..).
    • Inside setState you've to use similar states' names to that of your elements' names attribute. For the code snippet you provided you can add a name attribute to the first input tag <input name = "firstName" .... /> and so on.
    • Having combinations of inputs of different types at the same time (e.g. text area and checkboxes) are trickier to deal with you might need to modify it a little or using conditions but you get the idea now :)
    • One more thing don't bind your handlers inside the render() method beacuse with each render a brand new function returns one of the correct ways to bind the handlers is inside the constructor() method.