0
\$\begingroup\$

This code works as is but I'd like to learn if there's any way it could be simplified or cleaner looking.

There are 3 dropdowns. Each dropdown's list of options are based on a single array of options.

If DD1 is set to 'A', DD2 is set to 'B', and DD3 is set to 'C' - while the options are ['A', 'B', 'C', 'D'] - One dropdown cannot select an option that is already in use by another dropdown.

In this situation, for example, DD1 would only allow you to choose from 'A' or 'D' because the other letters are already being used.

Parent

<ManageContactOrder options={['A', 'B', 'C', 'D']} order={{1: 'A', 2: 'B', 3: 'C'} action={this.getUpdatedOrder}/>

Child

class ManageContactOrder extends Component {

  constructor(props){
    super(props)
    let config = this.updateDropdownOptions();

    this.state = {
      order: config[0],
      availableOptions1: config[1],
      availableOptions2: config[2],
      availableOptions3: config[3]
    }
  }

  updateDropdownOptions(orderPassedIn){
    let options = this.props.options;
    let order = orderPassedIn ? orderPassedIn : this.props.order;

    let availableOptions1 = options.filter(option => !Object.values(order).includes(option));
    availableOptions1.push(order[1]);

    let availableOptions2 = options.filter(option => !Object.values(order).includes(option));
    availableOptions2.push(order[2]);

    let availableOptions3 = options.filter(option => !Object.values(order).includes(option));
    availableOptions3.push(order[3]);

    return [order, availableOptions1, availableOptions2, availableOptions3]
  }

  onChange = async (e, contactNumber) => {
    let selectedValue = e.target.value;
    let order = this.state.order;
    order[contactNumber] = selectedValue;
    let config = this.updateDropdownOptions(order);
    this.props.action(order);
    this.setState({
      order: config[0],
      availableOptions1: config[1],
      availableOptions2: config[2],
      availableOptions3: config[3]
    });
  }

  render() {
    const { order, availableOptions1, availableOptions2, availableOptions3 } = this.state;

    return (
      <>
         <DropDown 
          options={availableOptions1}
          name='contact-order-one'
          id='contact-order-one'
          onChange={e => this.onChange(e, 1)}
          fieldValue={order[1]}
          data-testid='contact-order-one'
        />
          <DropDown 
          options={availableOptions2}
          name='contact-order-two'
          id='contact-order-two'
          onChange={e => this.onChange(e, 2)}
          fieldValue={order[2]}
          data-testid='contact-order-two'
        />
        <DropDown 
          options={availableOptions3}
          name='contact-order-three'
          id='contact-order-three'
          onChange={e => this.onChange(e, 3)}
          fieldValue={order[3]}
          data-testid='contact-order-three'
        />
      </>
    )
  }
}
\$\endgroup\$
  • \$\begingroup\$ So we can assume what you have is working as intended? \$\endgroup\$ – πάντα ῥεῖ Aug 9 at 17:15
  • \$\begingroup\$ It is working as intended, yes. @πάνταῥεῖ \$\endgroup\$ – Nate Thompson Aug 9 at 17:29
  • \$\begingroup\$ "I realize, as it is, the updated values won't be sent back up." So that's intended? \$\endgroup\$ – πάντα ῥεῖ Aug 9 at 17:35
  • \$\begingroup\$ Yes. My main focus right now is only maintaining what is happening inside of the child component. @πάνταῥεῖ \$\endgroup\$ – Nate Thompson Aug 9 at 17:41
  • \$\begingroup\$ It sends the new order back up to the parent now. Take a look. Should be less confusing now... @πάνταῥεῖ \$\endgroup\$ – Nate Thompson Aug 9 at 17:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.