2

I am working on someone else's code and trying to figure out how to render a list alphabetically in React. I didn't write any of this and have very little knowledge of React, so please bear with me.

The ul looks like this:

<ul className="prod-group__filter__options" ref={(options) => this.options = options}>
    {
        filter.dropdown.map((option, index) => (
            this.renderOption(filter, option, index)
        ))
    }
</ul>

and the renderOption function, which obviously renders the list items looks like this:

renderOption(filter, option, index) {
    return (
        <li className="prod-group__filter__option" key={index}>
            <label className="prod-group__filter__option__label">
                <input name={filter.name}
                       type="checkbox"
                       defaultValue={option.slug}
                       checked={option.checked}
                       onChange={this.optionChangeHandler} />
                {option.label}
            </label>
        </li>
    );
}

The value I am trying to alphabetize is option.slug which is coming from a json list. Can anyone help me get a bit closer to rendering this list alphabetically?

hmoore
  • 155
  • 1
  • 3
  • 13
  • 1
    Possible duplicate of [Sort array of objects by string property value in JavaScript](https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value-in-javascript) – Tom Fenech Aug 28 '17 at 16:13

3 Answers3

2

It looks like filter.dropdown is your array of options. This array is passed to the .map() method which then runs a renderOption method in the given order.

Hence, you should sort the filter.dropdown array in your ul component code just before calling .map() on it.

macbem
  • 1,180
  • 2
  • 9
  • 21
2

You will have to sort option alphabetically using plain javascript before calling filter.dropdown.map... on it. I would advice using lodash function _.sortBy(option, 'slug'); where option is an array of objects with a property called slug then you can pass the sorted result to your map function.

kimobrian254
  • 557
  • 3
  • 10
  • Thanks finch! Can you possibly give me an example? Since the slug (or value) is only a part of the list item how do I render the full list items alphabetized and not just a list of alphabetized slugs? – hmoore Aug 28 '17 at 16:41
  • 2
    Here's a [codepen](https://codepen.io/brian_kim/pen/PKydOv?editors=0001) sorting and mapping names and cities. More info on lodash [_sortBy](https://lodash.com/docs/4.17.4#sortBy) – kimobrian254 Aug 28 '17 at 21:37
0

In case anyone is interested, the solution was to sort the list items before calling .map() on it as both macbem and finch suggested. I used const to create an "items" constructor that I could then pass into the ul further down:

const items = [].concat(this.props.options)
  .sort((a, b) => {
    const One = a.slug.toUpperCase();
    const Two = b.slug.toUpperCase();

    return (One < Two) ? -1 : (One > Two) ? 1 : 0;
  })
  .map((option, index) => this.renderOption(name, option, index));

return (
  <div className={classes}>
    <a className="prod-group__filter__dropdown"
       ref={(trigger) => this.trigger = trigger}
       onClick={this.triggerClickHandler}>
      {label}
    </a>
    <ul className="prod-group__filter__options" ref={options => this.options = options}>
      { items }
    </ul>
  </div>
);
hmoore
  • 155
  • 1
  • 3
  • 13