question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Autocomplete] Grouping logic is broken

See original GitHub issue
  • The issue is present in the latest release.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 😯

Given a set of data and the groupBy functor:

const data = [
  {
    group: 1,
    value: "A",
    intrinsicProperty: "#"
  },
  {
    group: 2,
    value: "B",
    intrinsicProperty: "#"
  },
  {
    group: 2,
    value: "C",
    intrinsicProperty: "#"
  },
  {
    group: 1,
    value: "D",
    intrinsicProperty: "#"
  }
];


const groupBy = datum => datum.group

The logic as described here produces a grouping of:

[
  {
    "key": 1,
    "index": 0,
    "options": [
      {
        "group": 1,
        "value": "A"
      }
    ]
  },
  {
    "key": 2,
    "index": 1,
    "options": [
      {
        "group": 2,
        "value": "B"
      },
      {
        "group": 2,
        "value": "C"
      }
    ]
  },
  {
    "key": 1,
    "index": 3,
    "options": [
      {
        "group": 1,
        "value": "D"
      }
    ]
  }
]

Which either:

  • shows on the Autocomplete suggestions as
 1:
    A
 2:
    B
    C
 1:
    D
  • crashes the app with
Warning: Encountered two children with the same key, `1`. Keys should be unique so that components maintain their identity across updates.

Expected Behavior 🤔

I expect that the grouping would look something like this:

 1:
    A
    D
 2:
    B
    C

Steps to Reproduce 🕹

Steps:

  1. Go to https://codesandbox.io/s/withered-silence-jcrgd
  2. Click on the input box
  3. See error

Context 🔦

The logic linked in “Current Behavior” is flawed, particularly this part:

if (acc.length > 0 && acc[acc.length - 1].key === key) {
    acc[acc.length - 1].options.push(option);
} else {
    acc.push({
        key,
        index,
        options: [option],
    });
}

A more contrived example:

const data = [
    { group: 1, value: "A" },
    { group: 2, value: "B" },
    { group: 2, value: "C" },
    { group: 1, value: "D" },
    { group: 3, value: "E" },
    { group: 2, value: "F" },
    { group: 1, value: "G" }
]

const groupBy = datum => datum.group

Running the ‘faulty’ logic yields the result (which causes buggyness due to duplicate key):

[ { key: 1, index: 0, options: [ [Object] ] },
  { key: 2, index: 1, options: [ [Object], [Object] ] },
  { key: 1, index: 3, options: [ [Object] ] },
  { key: 3, index: 4, options: [ [Object] ] },
  { key: 2, index: 5, options: [ [Object] ] },
  { key: 1, index: 6, options: [ [Object] ] } ]

Replacing the logic with:

if (groupBy) {
  let index = 0
  const indexByKey = {}
  const result = []
  for (const option of filteredOptions) {
    const key = groupBy(option)
    if (indexByKey[key] === undefined) {
      indexByKey[key] = index
      result.push({
        key,
        index,
        options: []
      })
      index++
    }
    result[indexByKey[key]].options.push(option)
  }
  let counter = 0
  for (const option of result) {
    option.index = counter
    counter += option.options.length
  }
  groupedOptions = result
}

yields the correctly grouped options:

[ { key: 1, index: 0, options: [ [Object], [Object], [Object] ] },
  { key: 2, index: 3, options: [ [Object], [Object], [Object] ] },
  { key: 3, index: 6, options: [ [Object] ] } ]

Your Environment 🌎

Tech Version
Material-UI Core v4.8.3
Material-UI Lab v4.0.0-alpha.39
React v16.11.0
Browser Chrome
TypeScript v3.7.2

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
Janpotcommented, Jan 6, 2020

🙂 Also be careful with this code, it will break on:

const groupBy = () => 'toString'

I’d suggest to use

const indexByKey = Object.create(null)

or a Map

0reactions
oliviertassinaricommented, Mar 19, 2021

@jeunesseBurce Please ask support questions on StackOverflow

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Autocomplete] Grouping logic is broken · Issue #19109 - GitHub
The issue is present in the latest release. I have searched the issues of this repository and believe that this is not a...
Read more >
Material-UI AutoComplete Grouping logic does not honor ...
And I wanted it to be grouped by its parent node. Would this be possible using AutoComplete? data is like as follows:
Read more >
React Autocomplete component - Material UI - MUI
This is a function that accepts an object with two fields: group —a string representing a group name; children —a collection of list...
Read more >
Autofill: What web devs should know, but don't - Cloud Four
Safari Autofill working with two fields, but not working with one field ... is the ability to declare an arbitrary section to group...
Read more >
Grouping in Blazor AutoComplete Component | Syncfusion
The AutoComplete supports wrapping nested elements into a group based on different categories. The category of each list item can be mapped through...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found