Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested form state and one onChange function in React

Tags:

forms

reactjs

I'm working on a form in React. I have nested state in MatchForm component and "bind" values from state with different inputs. I would like to have on onChange function which manages all cinput changes and pass it to state. Current onChange function works when I have only lineup inputs. But when I added other inputs I have no idea how to handle with it. How should I name inputs and how onChange function should look like to work with all inputs (without many ifs)?

Thank you in advance

class MatchForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      lineup: {
        setter: '',
        receiver1: '',
        receiver2: '',
        attacker: '',
        blocker1: '',
        blocker2: '',
        libero: ''
      },
      distribution: {
        receiver1: 20,
        receiver2: 20,
        attacker: 20,
        blocker1: 20,
        blocker2: 20
      },
      risk: 'normal',
      default: false
    };

    this.onChange = this.onChange.bind(this);
  }

  onChange(e) {
    this.setState({lineup: { ...this.state.lineup, [e.target.name]:e.target.value } })
    }

  render() {
    return (
      <div>
        {
          Object.keys(this.state.lineup).map((el,i) =>
            <select
              key={i}
              name={el}
              onChange={this.onChange}
              value={this.state.lineup[el]}
            >
              <option value="" disabled>{el}</option>
              <option value="Marian Noga">Marian Noga</option>
              <option value="Janek Kowalski">Janek Kowalski</option>
            </select>
          )
        }
        {
          Object.keys(this.state.distribution).map((el,i) =>
            <Field
              key={i}
              field={el}
              label={el}
              type='number'
              value={this.state.distribution[el]} 
              onChange={this.onChange} />    
              )
        }
        <select
          name="risk"
          onChange={this.onChange}
          value={this.state.risk}
        >
          <option value="" disabled>risk</option>
          <option value="safe">safe</option>
          <option value="normal">normal</option>
          <option value="risk">risk</option>
          </select>
          <label><input name="default" type="checkbox" value={this.state.default} onChange={this.onChange} /> Set as default lineup</label>
      </div>
    )
  }
}

export default MatchForm
like image 281
magnat Avatar asked Dec 07 '25 13:12

magnat


1 Answers

You can bind the onChange function with different values for each of your fields:

onChange={this.onChange.bind(this, 'lineup', el)}

Then if you write your onChange like this:

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

You should be able now to repeat that for each of your fields.

like image 52
Waiski Avatar answered Dec 09 '25 01:12

Waiski