Skip to content

Conversation

@kysedate
Copy link
Contributor

@kysedate kysedate commented May 4, 2018

Pull request checklist

  • Addresses an existing issue: Fixes #0000
  • Include a change request file using $ npm run change

When 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:

<ParentComponent>
     <ChildComponent styles={getStyles()}>
          {renderGrandchildComponent()} 
     </ChildComponent>
</ParentComponent>

Even if the ParentComponent doesn't update (shouldComponentUpdate returns false), getStyles() and renderGrandchildComponent() 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.

kysedate and others added 8 commits January 31, 2018 16:37
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.
@jspurlin jspurlin self-requested a review May 4, 2018 23:12
@jspurlin
Copy link
Contributor

jspurlin commented May 4, 2018

@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.

Copy link
Contributor

@jspurlin jspurlin left a 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

@christiango
Copy link
Member

@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

@kysedate
Copy link
Contributor Author

kysedate commented May 9, 2018

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.

@jspurlin jspurlin merged commit 76e7918 into microsoft:master May 9, 2018
Markionium added a commit to Markionium/office-ui-fabric-react that referenced this pull request May 13, 2018
…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)
Markionium added a commit to Markionium/office-ui-fabric-react that referenced this pull request May 13, 2018
* 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)
  ...
@microsoft microsoft locked as resolved and limited conversation to collaborators Aug 31, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants