Choices: Performance issues - setChoiceByValue() and form.reset();

Created on 13 Jan 2019  路  7Comments  路  Source: Choices-js/Choices

I started to use Choices.js instead of select2 in my project, but ran into performance issues, when i'm having ~1000 options in my employee list with a simple "single-select" setup .

Every time I refresh the user datasheet form containing my Choices dropdown (making form.reset() + using setChoiceByValue() to select the current employee-manager from the dropdown), Choices will re-render the HTML content of the dropdown multiple times (by making incredible amount HTML parses), however there is no point of doing this. This causes ~3000 ms (!) lag when refreshing a simple user datasheet.

I can see Choices.js binds handler to form.reset() event, which alone causes 450 ms HTML rendering time for Chrome.

With select2 this action has taken just 150-200 ms. Is there any workaround to avoid this rendering overhead in Choices?

stale

Most helpful comment

Thanks for the suggestions - I've just merged another fix which will hopefully solve the performance issue you are seeing. It will go out in the next release

All 7 comments

I can confirm this is an issue for me as well but with setChoices() method. About 500 or more records being set into a Choices single selector takes 15+ seconds for me. Unacceptable performance.

Unfortunately I faced a more serious performance issue ever since. As choices binds it's click handlers to the root document, a single click on any HTML Element on a page (even on an empty div) will result in re-rendering all choices lists on the page causing the page to stop responding for seconds.

There seems to be no response on this issue from the authors in 3 weeks, so I must start to find an alternative library. What a pity! Without these issues Choices would be a top pick. Any ideas on alternatives?

I started to debug, and found the bugs in the code in choices.js from line 1461.
Current:

if (hasHighlightedItems) {
  this.unhighlightAll();
}

Fixed:

if (hasHighlightedItems.length > 0) {
  this.unhighlightAll();
}

Because [] expands to truthy, not falsy.
@jshjohnson: could you fix it please? This library is awesome anyways, thank you for your work!

Furthermore, on line 495:

const stateChanged =
  this._currentState.choices !== this._prevState.choices ||
  this._currentState.groups !== this._prevState.groups ||
this._currentState.items !== this._prevState.items;

will always return true, because all these properties are arrays, and if they are not references of each other (they are not), they cannot be compared this way. Even if they are empty:

[] === []
// returns false

In addition, this is valid for the objects inside these arrays. I suppose, if this is fixed, it might solve all the above mentioned issues.

Thanks for the suggestions - I've just merged another fix which will hopefully solve the performance issue you are seeing. It will go out in the next release

Thank you, Josh! I'm looking forward to the next release!

Thanks for contributing to this issue. As it has been 60 days since the last activity, this issue is being automatically closed. This is often because the request was already solved in some way and it just wasn't updated or it's no longer applicable. If that's not the case, please do feel free to either reopen this issue or open a new one. We'll gladly take a look again!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ryanbuening picture ryanbuening  路  4Comments

sebastien-roch picture sebastien-roch  路  3Comments

zslabs picture zslabs  路  6Comments

stephendolan picture stephendolan  路  3Comments

alfonsoar picture alfonsoar  路  4Comments