Filter asMap computed value maintaining sort order?

103 views Asked by At

Using Mobx, I am trying to output the titles of the books from the booksByIdMap in the same order they are in the booksSortedIdArray:

class BookStore {
  @observable booksSortedIdArray = ["88cd7621", "88cd7624", "88cd7623", "88cd7622"];
  @observable booksByIdMap = asMap({
    "88cd7621": {
      "id": "88cd7621",
      "title": "The Secret"
    },
    "88cd7622": {
      "id": "88cd7622",
      "title": "The Alchemist"
    },
    "88cd7623": {
      "id": "88cd7623",
      "title": "Javascript"
    },
    "88cd7624": {
      "id": "88cd7624",
      "title": "PHP"
    }
  });

  @computed get byBookId() {
    return this.booksByIdMap.values().filter(b => this.booksSortedIdArray.includes(b.id));
  }
}

The filter in the byBookId does not seem to maintain that sort order and instead outputs:

The Secret, The Alchemist, Javascript, PHP

as opposed to:

The Secret, PHP, Javascript, The Alchemist

Here is a fiddle.

How can I output the titles based on the sort order of ids in booksSortedIdArray?

1

There are 1 answers

0
Tholle On BEST ANSWER

You could use reduce on the array and try to get each key from the map. If it exists, just add it to the result. This way you will get it in order:

class BookStore {
  @observable booksSortedIdArray = ["88cd7621", "88cd7624", "88cd7623", "88cd7622"];
  @observable booksByIdMap = asMap({
    "88cd7621": {
      "id": "88cd7621",
      "title": "The Secret"
    },
    "88cd7622": {
      "id": "88cd7622",
      "title": "The Alchemist"
    },
    "88cd7623": {
      "id": "88cd7623",
      "title": "Javascript"
    },
    "88cd7624": {
      "id": "88cd7624",
      "title": "PHP"
    }
  });

  @computed get byBookId() {
    return this.booksSortedIdArray.reduce((res, el) => {
      const book = this.booksByIdMap.get(el);
      if(book) {
        res.push(book);
      }
      return res;
    }, []);
  }
}