survivejs / react-book

From apprentice to master (CC BY-NC-ND)

Home Page:https://survivejs.com/react/introduction/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Improvement] NoteStore.getNotesByIds

vjancik opened this issue · comments

The current implementation (Code link):

getNotesByIds(ids) {
  return (ids || []).map(
    id => this.notes.filter(note => note.id === id)
  ).filter(a => a.length).map(a => a[0]);
}

Can be written much simpler as:

getNotesByIds(ids) {
    return this.notes.filter(note =>
      (ids || []).includes(note.id));
  }

In book (v2.1.0): page 105

I remember trying something simpler like this. There's one huge gotcha if I remember right. getNotesByIds must be ordered based on ids. That's why we need to do it in a little convoluted way.

Let's keep this open, though, as I want to revisit this and document better what's going on. 👍

getNotesByIds must be ordered based on ids

Do you mean "sort smallest id to earliest in list"? If so, perhaps you should have the sortNotesByIds function separate, which is called after getNotesByIds? Or if @vjancik does collect the notes sorted by smallest first naturally, then add a test to prove it, that way the test acts like an intention documentation.

If there was a need for more performant code, sometime I'll leave in the older slow-but-clear code in as a comment, & faster but confusing code after.

Splitting up the problem could work. We would get a simple filter at getNotesByIds as suggested. We would then apply the order on that. That sounds sane to me. 👍

I ended up doing

getNotesByIds(ids) {
  // `reduce` is a powerful method that allows us to
  // fold data. You can implement `filter` and `map`
  // through it. Here we are using it to concatenate
  // notes matching to the ids.
  return (ids || []).reduce((notes, id) =>
    // Concatenate possible matching ids to the result
    notes.concat(
      this.notes.filter(note => note.id === id)
    )
  , []);
}

That's a little neater than the old solution while retaining the order. 👍