-5

component

populateOptions() {
    return this.props.options.map((option, i) => (
      <optgroup key={i} label={option.text}>
        {option.value.map((entry) => (
          <option>{entry.text}</option>
        ))}
      </optgroup>
    ));
 }

  render() {
    console.log(this.props.options);
    return (
      <div style={{position: 'relative'}} data-testid='select-list'>
        {this.props.title ? <label htmlFor={this.props.name}>

{this.props.title}</label> : ''}

    <div className={`select-list ${this.props.isInvalid ? 'input-field-error' : ''}`}>
      <select
        id={this.props.name}
        name={this.props.name}
        onBlur={this.handleOnBlur}
        onChange={this.handleChange}
        onFocus={this.handleOnFocus}
        tabIndex={this.props.tabIndex}
        type='text'
        value={this.props.value}>
        <option value='' disabled />
        {this.props.options.length > 0 && this.populateOptions()}
      </select>
      <div className='error-message'>{this.props.errorMessage}</div>
    </div>
    {this.props.description ? (
      <Tooltip
        alwaysVisibleMobile={true}
        text={this.props.description}
        shouldDisplay={this.state.isInputOnFocus}
        position={this.props.tooltipPosition}
        width={this.props.tooltipWidth}
      />
    ) : (
      ''
    )}
  </div>
);
  }
}

SelectList.propTypes = {
  description: PropTypes.string,
  errorMessage: PropTypes.string,
  isInvalid: PropTypes.bool,
  handleFieldValidation: PropTypes.func,
  name: PropTypes.string,
  onChange: PropTypes.func,
  onFocus: PropTypes.func,
  options: PropTypes.array,
  required: PropTypes.bool,
  tabIndex: PropTypes.number,
  title: PropTypes.string,
  tooltipPosition: PropTypes.string,
  tooltipWidth: PropTypes.string,
  value: PropTypes.any
};

data to be mapped

 {
  "description": "",
  "required": true,
  "title": "What is the finance for?",
  "errorMessage": "Please select an item in this list",
  "type": "select",
  "name": "finance_purpose",
  "options": [
    {
      "text": "Cashflow",
      "value": [
        {
          "text": "Stock purchase",
          "value": "stock"
        },
        {
          "text": "Equipment repairs",
          "value": "equipment_repairs"
        },
        {
          "text": "Bill or tax payment",
          "value": "bill_or_tax_payment"
        },
        {
          "text": "Debt refinancing",
          "value": "debt_refinancing"
        },
        {
          "text": "Seasonal trading",
          "value": "seasonal_trading"
        },
        {
          "text": "New contract",
          "value": "new_contract"
        },
        {
          "text": "Facilities improvement",
          "value": "facilities_improvement"
        },
        {
          "text": "Refurbishment",
          "value": "refurbishment"
        },
        {
          "text": "Cashflow headroom",
          "value": "cashflow_headroom"
        },
        {
          "text": "Experienced a bad debt",
          "value": "experienced_a_bad_debt"
        },
        {
          "text": "Other cashflow or working capital",
          "value": "other_cashflow"
        }
      ]
    },
    {
      "text": "Asset purchase",
      "value": [
        {
          "text": "Transport vehicles",
          "value": "transport_vehicles"
        },
        {
          "text": "Construction vehicles",
          "value": "construction_vehicles"
        },
        {
          "text": "Construction equipment",
          "value": "construction_equipment"
        },
        {
          "text": "Machinery",
          "value": "machinery"
        },
        {
          "text": "Printing equipment",
          "value": "printing_equipment"
        },
        {
          "text": "Agricultural equipment",
          "value": "agricultural_equipment"
        },
        {
          "text": "Other asset purchase",
          "value": "other_asset_purchase"
        }
      ]
    }
  ]
},

So I'm getting this error Cannot read property value of undefined and I'm not sure why as all I'm trying to do is a map inside of map, does anyone have any ideas? When I console log "*console.log(option.value.map((entry) => entry.text))*" I get the data I want in the console but the page still errors and doesn't load.

Ideally I'd like the code to look like

populateOptions() {
    return this.props.options.map((option, i) => (
      <optgroup key={i} label={option.text}>
        <option>{option.value.map((entry) => entry.text)}</option
      </optgroup>
    ));
}
rednate95
  • 19
  • 7
  • 2
    Please avoid images of code and provide anything needed in the question itself. – Emile Bergeron Jul 25 '19 at 14:24
  • 2
    Please don't post images of your code. There are [several reasons](https://meta.stackoverflow.com/a/285557/6612182) that this is not encouraged on SO. – Rallen Jul 25 '19 at 14:25
  • Can you log `this.props.options` ? – Gaël S Jul 25 '19 at 14:28
  • try this : – Roy.B Jul 25 '19 at 14:28
  • Possibly related to how the [console evaluates data later](https://stackoverflow.com/q/17546953/1218980) which would give a false positive when debugging. – Emile Bergeron Jul 25 '19 at 14:29
  • @Roy.B that solution didn't work, now I get the error option is not defined. – rednate95 Jul 25 '19 at 15:35
  • console.log(this.props.options) gives me this roughly. (5) [{…}, {…}, {…}, {…}, {…}] 0: text: "Cashflow" value: Array(11) 0: {value: "stock", text: "Stock purchase"} – rednate95 Jul 25 '19 at 15:37

2 Answers2

0

You need to iterate like this,

populateOptions() {
    return this.props.options.map((option, i) => (
      <optgroup key={i} label={option.text}>
        {option.value.map((entry) => <option>{entry.text}</option>)}
      </optgroup>
    ));
  }

Also make sure you are getting values in props

{this.props.options.length > 0 && this.populateOptions()}

Demo

ravibagul91
  • 20,072
  • 5
  • 36
  • 59
0
populateOptions() {
 let optionsData = this.props.options;
 return optionsData.map(({text, value}, i) => {
  return Array.isArray(value) ? (
    <optgroup key={i} label={text}>
      {value.map(({text}, j) => (
        <option key={j}>{text}</option>
      ))}
    </optgroup>
  ) : (
    <option key={i} value={value}>
      {text}
    </option>
  );
});

}

In the end this worked the way I needed it to, I needed to do a check to make sure value was an actual array too. Thank you for your help.

rednate95
  • 19
  • 7