2

I need to update my top level state from a child component. The child component has multiple select lists for this purpose.

In my child component:

constructor(props) {
  this.updateNoOfSets = this.updateNoOfSets.bind(this);
  this.updateNoOfRounds = this.updateNoOfRounds.bind(this);
}

updateNoOfSets() {
  this.props.updateNoOfSets(parseInt(this.updatedNoOfSets.value));
}

updateNoOfRounds() {
  this.props.updateNoOfRounds(parseInt(this.updatedNoOfRounds.value));
}

<select
  value={this.props.noOfSets}
  onChange={this.updateNoOfSets}
  ref={(input) => {
    this.updatedNoOfSets = input;
  }}
>
  <option>1</option>
  <option>2</option>
  <option>3</option>
</select>

<select
  value={this.props.noOfRounds}
  onChange={this.updateNoOfRounds}
  ref={(input) => {
    this.updatedNoOfRounds = input;
  }}
>
  <option>1</option>
  <option>2</option>
  <option>3</option>
</select>

In my parent:

constructor(props) {
  super(props);
  this.updateNoOfSets = this.updateNoOfSets.bind(this);
  this.updateNoOfRounds = this.updateNoOfRounds.bind(this);
}

updateNoOfSets(noOfSets) {
  this.setState({'noOfSets': noOfSets});
}

updateNoOfRounds(noOfRounds) {
  this.setState({'noOfRounds': noOfRounds});
}

This is working but seems quite verbose to me. Is there a shorter way of writing this? My code example only has 2 select lists but my actual application has fare more.

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
Evanss
  • 23,390
  • 94
  • 282
  • 505

1 Answers1

0

You don't need multiple handlers for each of your select elements. All you need is a single handler that is intelligent enough

child:

constructor(props) {
  this.updateValue = this.updateValue.bind(this);
}

updateValue(item, value) {
  this.props.updateValue(item, parseInt(value));
}

<select
  value={this.props.noOfSets}
  onChange={(e) => this.updateValue('noOfSets', e.target.value)}
>
  <option>1</option>
  <option>2</option>
  <option>3</option>
</select>

<select
  value={this.props.noOfRounds}
  onChange={(e) => this.updateValue('noOfRounds', e.target.value)}
>
  <option>1</option>
  <option>2</option>
  <option>3</option>
</select>

Parent:

constructor(props) {
  super(props);
  this.updateValue = this.updateValue.bind(this);
}

updateValue(item, value) {
  this.setState({[item]: value});
}

EDIT: Keep in mind that binding functions in the render method is not a good idea as each time render is executed a new function is returned, take a look at this answer on how to avoid binding in render method

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Out of interest why does item need to be [item]? I can confirm that it doesnt work without the square brackets but I dont know why this is the case. – Evanss Nov 08 '17 at 04:18
  • 1
    dynamic keys needs to be written with square brackets otherwise they themself will be treated as a key – Shubham Khatri Nov 08 '17 at 05:20