0

I am writing a react component with two react-select fields whenever both the fields have a value I need to pass the combined object to the parent as a call back. One way I know is to store both of the options in onchange in a state and combine them and send them. However since there needs to be performance metrics I am trying to minimise re renders using state changes.

Heres a pseudo code of what I have right now. The onchange method in both sets a state but I dont want that re render to happen.

fieldSelectorChange = option => {
    this.setState(
      {
        option,
      },
    );
  };


<Select
      options={ fields }
      value={ sortedField }
      searchable
      placeholder={ trans( 'Find an option' ) }
      onChange={ this.fieldSelectorChange }
      autoFocus
    />
    <Select
      options={ sortOptions }
      value={ sortedOrder }
      defaultValue={ sortOptions[ 0 ] }
      placeholder={ trans( 'Choose' ) }
      onChange={ this.fieldSelectorChange }
    />
2
  • get real code first then we can talk. This is not specific enough. How to ask Commented Mar 30, 2020 at 18:41
  • updated @MikeTung Commented Mar 30, 2020 at 18:51

1 Answer 1

1

Without button

onSelect1Change(e) {
  this.setState({ select1value: e.target.value });
  if (this.state.select2value) {
    this.props.parentCallback({
      value1: e.target.value,
      value2: this.state.select2value
    })
  }
}

onSelect2Change(e) {
  this.setState({ select2value: e.target.value });
  if (this.state.select2value) {
    this.props.parentCallback({
      value1: this.state.select1value,
      value2: e.target.value,
    })
  }
}

/* ... */
<Select value={this.state.select1value} onChange={onSelect1Change} /* ... */ />
<Select value={this.state.select2value} onChange={onSelect2Change} /* ... */ />

Without button and only one onChange

One onSelectChange as you asked, but in this case you recreate arrow functions every render and it's not well-optimised.

onSelectChange(field, value) {
  this.setState({ [field]: value });

  if (this.state.select1value && this.state.select2value) {
    this.props.parentCallback({
      value1: value,
      value2: this.state.select2value
    })
  }
}

/* ... */
<Select
  value={this.state.select1value}
  onChange={e => this.onSelectChange('select1value', e.target.value)}
  /* ... */
/>
<Select
  value={this.state.select1value}
  onChange={e => this.onSelectChange('select2value', e.target.value)}
  /* ... */
/>

If you want to avoid this, you have to create two more functions and use them inside of your components

onSelect1Change = e => this.onSelectChange('select1value', e.target.value)
onSelect2Change = e => this.onSelectChange('select2value', e.target.value)

You can also add some validation here is you want:

if (field in this.state) {
  this.setState({ [field]: value });
} else {
  // field is missing, do something with this case
}

Form and sumbit

It's a common practive to wrap input fields in a form component.

onSelect1Change(e) {
  this.setState({ select1value: e.target.value });
}

onSelect2Change(e) {
  this.setState({ select2value: e.target.value });
}

onSumbit(e) {
  e.preventDefault();
  /* get both values from state and do something */
  console.log(this.state.select1value, this.state.select2value);
}
/* ... */
<form onSubmit={onSubmit}>
  <Select value={this.state.select1value} onChange={onSelect1Change} /* ... */ />
  <Select value={this.state.select2value} onChange={onSelect2Change} /* ... */ />
  <input type="submit" value="Submit" />
</form>

Button

But you can do it without form as well. You can just make a button and get values from state on user click.

onSelect1Change(e) {
  this.setState({ select1value: e.target.value });
}

onSelect2Change(e) {
  this.setState({ select2value: e.target.value });
}

onClick(e) {
  e.preventDefault();
  /* get both values from state and do something */
  console.log(this.state.select1value, this.state.select2value);
}
/* ... */
<div>
  <Select value={this.state.select1value} onChange={onSelect1Change} /* ... */ />
  <Select value={this.state.select2value} onChange={onSelect2Change} /* ... */ />
  <button onClick={onClick}>Click me!</button>
</div>
Sign up to request clarification or add additional context in comments.

7 Comments

thers is no submit button per se. Data must get sorted whenever there is a value. So if we select one of the dropdown and there is some value previously selected in the other select then also it should return the data in the call back
@leo okay, then you can try to you the first supposed solution
I would have used a form but since there is no on submit I dont think that I could do that.
@leo My first solution works with this.props.parentCallback property. If both select have values the parentCallback calls :) This solution doesn't require forms and buttons. Note: Since we don't have centralized function to check everything, we have to check condition inside of each onSelectChange function.
so there is no workaround but to use two setState ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.