Uj Corb
Uj Corb

Reputation: 2159

return array of objects from props React JS

so I have the following component that is a dropdown list created using react-select.

import React from 'react'
import Select from 'react-select';

const options = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
  { value: 'vanilla', label: 'Vanilla' }
];


class MealsFilters extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedOption: null,
    };
  }

  handleChange = (selectedOption) => {
    this.setState({ selectedOption });
    console.log(`Option selected:`, selectedOption);
  }

  render() {
    const { selectedOption } = this.state;
    return (
      <div className="container my-3">
        <div className="row">
          <div className="col-lg-4 col-md-6 col-sm-8">
            <Select
            isMulti
            isSearchable
            placeholder={"catégories"}
            value={selectedOption}
            onChange={this.handleChange}
            options={options}
            />
          </div>
        </div>
      </div>
    )
  }
}

export default MealsFilters;

the options variable is the default one from the docs. I actually need to replace its values by each meal category available. To do so, as you can see, I need to create an array of objects with a value and a label.

this component accesses meal categories through props called meals that are like so:

console.log(this.props.meals);

=> [{
     id: 0,
     name: spaghettis,
     category: italian,
     price: 5.99},
    {
     id: 1,
     name: hamburger,
     category: american,
     price: 7.99},
     {
      etc.
      }, {}]

How can I take advantage of this.props.meals to get my options array of objects ?

EDIT: multiple meals can have the same category, and I need each category to only appear once in the options.

Upvotes: 1

Views: 3083

Answers (4)

HMR
HMR

Reputation: 39250

You could do something like this:

options={this.props.meals.map(
  ({id, name})=>({value:id,label:name})
)}

You could also use redux connect to create a container that will map the data to dropdown values for you

You can merge the data by category in the following way:

var items = [
  {
    id: 0,
    name: 'spaghettis',
    category: 'italian',
    price: 5.99,
  },
  {
    id: 1,
    name: 'hamburger',
    category: 'american',
    price: 7.99,
  },
  {
    id: 2,
    name: 'other hamburger',
    category: 'american',
    price: 7.99,
  },
];

console.log(
  [
    ...items.reduce(
      (result, item) => (
        result.get(item.category)
          ? result.get(item.category).push(item.id)
          : result.set(item.category, [item.id]),
        result
      ),
      new Map(),
    ),
  ].map(([label, value]) => ({ label, value })),
);

In the component it'll look like this:

options={[
  ...this.props.meals.reduce(
    (result, item) => (
      result.get(item.category)
        ? result.get(item.category).push(item.id)
        : result.set(item.category, [item.id]),
      result
    ),
    new Map(),
  ),
].map(([label, value]) => ({ label, value }))}

Upvotes: 1

ed&#39;
ed&#39;

Reputation: 1895

You can use getOptionLabel and getOptionValue props.

<Select
    options={this.props.meals},
    getOptionLabel={m => m.name}
    getOptionValue={m => m.id} />

https://react-select.com/props

getOptionLabel generic = (option) => string

Resolves option data to a string to be displayed as the label by components

getOptionValue generic = (option) => string

Resolves option data to a string to compare options and specify value attributes

Upvotes: 1

kockburn
kockburn

Reputation: 17606

You only need the "name" property so when you map through meals, simply retrieve it. Then upper case the first letter.

const meals = [{
    id: 0,
    name: "spaghettis",
    category: "italian",
    price: 5.99
  },
  {
    id: 1,
    name: "hamburger",
    category: "american",
    price: 7.99
  }
]

const result = meals.map(({name}) => ({
  label: `${name[0].toUpperCase()}${name.slice(1)}`,
  value: name
}))

console.log(result);

Upvotes: 1

Anurag Awasthi
Anurag Awasthi

Reputation: 6223

Map over your this.props.meals array, and create the needed options array,

<Select
    isMulti
    isSearchable
    placeholder={"catégories"}
    value={selectedOption}
    onChange={this.handleChange}
    options={this.props.meal.map(item=>({value: item.id, label: item.name}))}
/>

Upvotes: 2

Related Questions