-
Notifications
You must be signed in to change notification settings - Fork 2.9k
ComboBox: Option Performance Optimization #4782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ComboBox: Option Performance Optimization #4782
Conversation
Updating fork
merging master
Merge master into kysedate fork
…nentUpdate returns false), children functions are still being executed unnecessarily, which can cause performance issues. This can be avoided by passing in a reference to a function that returns the children elements, instead of returning the elements themselves.
|
@dzearing, @joschect, or @cliffkoh any ideas why a components children are being calculated/built when the component returns false from shouldComponentUpdate? Making the children be passed in as the result of a function doesn't hit this issue, shouldComponentUpdate returns false render is not running and hence the function that returns the children is not called. |
jspurlin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good to me, but I want to see if anyone else has info on why this is happening
|
@kysedate are you sure that the component should update is returning false here? Children is a prop passed to ParentComponent. In this case, it needs to call those functions in order to compute the props for ParentComponent |
|
Christian is right, one of the parameters to shouldComponentUpdate is newProps. This means that the new props have to be computed before they can be passed in to shouldComponentUpdate. Since the child component (and it's child component) was a prop, it had to build. Nonetheless, this change still prevents this from happening, since it is entierly unnecessary. |
…i-fabric-react into parallel-tsc * 'parallel-tsc' of https://github.com/Markionium/office-ui-fabric-react: Variants: have project use OUFR instead of just styling (microsoft#4854) Add more customization hooks to ProgressIndicator (microsoft#4566) Issue#4832: Break BaseButton Types hard dependency from class ContextualMenu (microsoft#4845) Applying package updates. Revert react portals change (microsoft#4840) Update ImageOverview.md Fixes duplicate reading of suggestions on people picker (microsoft#4765) Persona: Deprecate primaryText (microsoft#4811) Experiments: Fix Fluent theme color names (microsoft#4834) Applying package updates. Add JasonGore to command bar codeowners Fix index import (microsoft#4826) Added overflowMenuProps property to CommandBar (microsoft#4818) Fluent theme: Fix imports to use relative paths (microsoft#4831) ContextualMenuItem: adding secondaryText (microsoft#4788) ComboBox: Option Performance Optimization (microsoft#4782)
* master: (95 commits) Variants: have project use OUFR instead of just styling (microsoft#4854) Add more customization hooks to ProgressIndicator (microsoft#4566) Issue#4832: Break BaseButton Types hard dependency from class ContextualMenu (microsoft#4845) Applying package updates. Revert react portals change (microsoft#4840) Update ImageOverview.md Fixes duplicate reading of suggestions on people picker (microsoft#4765) Persona: Deprecate primaryText (microsoft#4811) Experiments: Fix Fluent theme color names (microsoft#4834) Applying package updates. Add JasonGore to command bar codeowners Fix index import (microsoft#4826) Added overflowMenuProps property to CommandBar (microsoft#4818) Fluent theme: Fix imports to use relative paths (microsoft#4831) ContextualMenuItem: adding secondaryText (microsoft#4788) ComboBox: Option Performance Optimization (microsoft#4782) Marqueeselection style update (microsoft#4803) Applying package updates. FocusZone: Add the ability to stop focus from propagating outside the FocusZone (microsoft#4823) Unknown persona coin (microsoft#4809) ...
Pull request checklist
$ npm run changeWhen investigating performance issues with our ComboBox, I ran into some React behaviour that I was not expecting. Even after breaking out the ComboBox Options into a wrapping component (which uses shouldComponentUpdate to avoid unnecessary updates), render time increased steadily as the number of options increased.
Take the following example:
Even if the ParentComponent doesn't update (shouldComponentUpdate returns false),
getStyles()andrenderGrandchildComponent()are still executed. This leads to the component computing a bunch of information (calculating styles, building JSX.Elements, etc. ) that is never actually used. Since the component isn't updated in the DOM, this information doesn't need to be computed.This leads to a performance hit with ComboBoxes that have many options and/or complex onRenderOption functions. To get around this, we can break out the component into it's own private render function, which will be called by the wrapper IF the component is going to be updated. By passing a reference to this function to the wrapper, we can ensure that this logic is never computed until we actually need it.
Focus areas to test
I have tested this ComboBox in the test app, and with complex scenarios (many options, custom styling, etc. ) and found that there is large performance increase with this change without any functionality regressions. The existing functionality of the ComboBox does not change. This PR does not change the times at which ComboBoxOptions are rendered, it only delays the calls of their child components until it is time to render.